From 3a4ce0a86b0b4c8fbb4d16ea62e508d5ab29dede Mon Sep 17 00:00:00 2001 From: Sridhar Periyasamy Date: Wed, 2 Mar 2016 16:20:45 -0500 Subject: [PATCH 01/31] Add support for building dotnet CLI on RHEL. --- .../OutputStandardOutputAndError/project.json | 2 +- .../CurrentPlatform.cs | 15 +++++- .../Enumerations/BuildPlatform.cs | 5 +- scripts/dotnet-cli-build/CompileTargets.cs | 54 +++++++------------ scripts/obtain/install.sh | 2 + test/EndToEnd/EndToEndTest.cs | 17 +++--- 6 files changed, 48 insertions(+), 47 deletions(-) diff --git a/TestAssets/TestProjects/OutputStandardOutputAndError/project.json b/TestAssets/TestProjects/OutputStandardOutputAndError/project.json index f9b804dda..8c87d36c9 100644 --- a/TestAssets/TestProjects/OutputStandardOutputAndError/project.json +++ b/TestAssets/TestProjects/OutputStandardOutputAndError/project.json @@ -5,7 +5,7 @@ }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23728" + "NETStandard.Library": "1.0.0-rc2-23811" }, "frameworks": { diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/CurrentPlatform.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/CurrentPlatform.cs index fb70d37c1..7fd8752ae 100644 --- a/scripts/Microsoft.DotNet.Cli.Build.Framework/CurrentPlatform.cs +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/CurrentPlatform.cs @@ -48,6 +48,15 @@ namespace Microsoft.DotNet.Cli.Build.Framework } } + public static bool IsRHEL + { + get + { + var osname = PlatformServices.Default.Runtime.OperatingSystem; + return string.Equals(osname, "rhel", StringComparison.OrdinalIgnoreCase); + } + } + private static BuildPlatform DetermineCurrentPlatform() { if (IsWindows) @@ -66,10 +75,14 @@ namespace Microsoft.DotNet.Cli.Build.Framework { return BuildPlatform.CentOS; } + else if (IsRHEL) + { + return BuildPlatform.RHEL; + } else { return default(BuildPlatform); } } } -} \ No newline at end of file +} diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/Enumerations/BuildPlatform.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/Enumerations/BuildPlatform.cs index d594ca604..715795196 100644 --- a/scripts/Microsoft.DotNet.Cli.Build.Framework/Enumerations/BuildPlatform.cs +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/Enumerations/BuildPlatform.cs @@ -5,6 +5,7 @@ namespace Microsoft.DotNet.Cli.Build.Framework Windows = 1, OSX = 2, Ubuntu = 3, - CentOS = 4 + CentOS = 4, + RHEL = 5 } -} \ No newline at end of file +} diff --git a/scripts/dotnet-cli-build/CompileTargets.cs b/scripts/dotnet-cli-build/CompileTargets.cs index e62fba929..1664ce7d7 100644 --- a/scripts/dotnet-cli-build/CompileTargets.cs +++ b/scripts/dotnet-cli-build/CompileTargets.cs @@ -238,9 +238,9 @@ namespace Microsoft.DotNet.Cli.Build // Find toolchain package string packageId; - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + if (CurrentPlatform.IsWindows) { - if (IsWinx86) + if (CurrentArchitecture.Isx86) { // https://github.com/dotnet/cli/issues/1550 c.Warn("Native compilation is not yet working on Windows x86"); @@ -249,24 +249,16 @@ namespace Microsoft.DotNet.Cli.Build packageId = "toolchain.win7-x64.Microsoft.DotNet.AppDep"; } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + else if (CurrentPlatform.IsUbuntu) { - var osname = PlatformServices.Default.Runtime.OperatingSystem; - if (string.Equals(osname, "ubuntu", StringComparison.OrdinalIgnoreCase)) - { - packageId = "toolchain.ubuntu.14.04-x64.Microsoft.DotNet.AppDep"; - } - else if (string.Equals(osname, "centos", StringComparison.OrdinalIgnoreCase)) - { - c.Warn("Native compilation is not yet working on CentOS"); - return c.Success(); - } - else - { - return c.Failed($"Unknown Linux Distro: {osname}"); - } + packageId = "toolchain.ubuntu.14.04-x64.Microsoft.DotNet.AppDep"; } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + else if (CurrentPlatform.IsCentOS || CurrentPlatform.IsRHEL) + { + c.Warn($"Native compilation is not yet working on {CurrentPlatform.Current}"); + return c.Success(); + } + else if (CurrentPlatform.IsOSX) { packageId = "toolchain.osx.10.10-x64.Microsoft.DotNet.AppDep"; } @@ -296,28 +288,20 @@ namespace Microsoft.DotNet.Cli.Build // Find crossgen string arch = PlatformServices.Default.Runtime.RuntimeArchitecture; string packageId; - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + if (CurrentPlatform.IsWindows) { packageId = $"runtime.win7-{arch}.Microsoft.NETCore.Runtime.CoreCLR"; } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + else if (CurrentPlatform.IsUbuntu) { - var osname = PlatformServices.Default.Runtime.OperatingSystem; - if (string.Equals(osname, "ubuntu", StringComparison.OrdinalIgnoreCase)) - { - packageId = "runtime.ubuntu.14.04-x64.Microsoft.NETCore.Runtime.CoreCLR"; - } - else if (string.Equals(osname, "centos", StringComparison.OrdinalIgnoreCase)) - { - // CentOS runtime is in the runtime.rhel.7-x64... package. - packageId = "runtime.rhel.7-x64.Microsoft.NETCore.Runtime.CoreCLR"; - } - else - { - return c.Failed($"Unknown Linux Distro: {osname}"); - } + packageId = "runtime.ubuntu.14.04-x64.Microsoft.NETCore.Runtime.CoreCLR"; } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + else if (CurrentPlatform.IsCentOS || CurrentPlatform.IsRHEL) + { + // CentOS runtime is in the runtime.rhel.7-x64... package. + packageId = "runtime.rhel.7-x64.Microsoft.NETCore.Runtime.CoreCLR"; + } + else if (CurrentPlatform.IsOSX) { packageId = "runtime.osx.10.10-x64.Microsoft.NETCore.Runtime.CoreCLR"; } diff --git a/scripts/obtain/install.sh b/scripts/obtain/install.sh index d973f9ff8..362e7a57c 100755 --- a/scripts/obtain/install.sh +++ b/scripts/obtain/install.sh @@ -83,6 +83,8 @@ current_os() echo "ubuntu" elif [ "$(cat /etc/*-release | grep -cim1 centos)" -eq 1 ]; then echo "centos" + elif [ "$(cat /etc/*-release | grep -cim1 rhel)" -eq 1 ]; then + echo "rhel.7" fi fi } diff --git a/test/EndToEnd/EndToEndTest.cs b/test/EndToEnd/EndToEndTest.cs index 1f734e3bb..f6f5663be 100644 --- a/test/EndToEnd/EndToEndTest.cs +++ b/test/EndToEnd/EndToEndTest.cs @@ -83,9 +83,9 @@ namespace Microsoft.DotNet.Tests.EndToEnd [Fact] public void TestDotnetBuildNativeRyuJit() { - if(IsCentOS()) + if(IsCentOSorRHEL()) { - Console.WriteLine("Skipping native compilation tests on CentOS - https://github.com/dotnet/cli/issues/453"); + Console.WriteLine("Skipping native compilation tests on CentOS/RHEL - https://github.com/dotnet/cli/issues/453"); return; } @@ -105,9 +105,9 @@ namespace Microsoft.DotNet.Tests.EndToEnd [Fact] public void TestDotnetBuildNativeCpp() { - if(IsCentOS()) + if(IsCentOSorRHEL()) { - Console.WriteLine("Skipping native compilation tests on CentOS - https://github.com/dotnet/cli/issues/453"); + Console.WriteLine("Skipping native compilation tests on CentOS/RHEL - https://github.com/dotnet/cli/issues/453"); return; } @@ -127,9 +127,9 @@ namespace Microsoft.DotNet.Tests.EndToEnd [Fact] public void TestDotnetCompileNativeCppIncremental() { - if (IsCentOS()) + if (IsCentOSorRHEL()) { - Console.WriteLine("Skipping native compilation tests on CentOS - https://github.com/dotnet/cli/issues/453"); + Console.WriteLine("Skipping native compilation tests on CentOS/RHEL - https://github.com/dotnet/cli/issues/453"); return; } @@ -236,7 +236,7 @@ namespace Microsoft.DotNet.Tests.EndToEnd Directory.SetCurrentDirectory(currentDirectory); } - private bool IsCentOS() + private bool IsCentOSorRHEL() { if(RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { @@ -244,7 +244,8 @@ namespace Microsoft.DotNet.Tests.EndToEnd if(File.Exists(OSIDFILE)) { - return File.ReadAllText(OSIDFILE).ToLower().Contains("centos"); + string osidcontent = File.ReadAllText(OSIDFILE).ToLower(); + return osidcontent.Contains("centos") || osidcontent.Contains("rhel"); } } From d4a3190bfc4e489a652b044d48305788db3368b1 Mon Sep 17 00:00:00 2001 From: Sridhar Periyasamy Date: Mon, 7 Mar 2016 12:20:50 -0800 Subject: [PATCH 02/31] Refactor the build scripts - Bifurcate Package and Publish targets to enable signing. - Move publish from bash/ps into c#. - Create multiple targets to create MSIs and Bundles. --- packaging/nuget/package.ps1 | 6 +- packaging/osx/package-osx.sh | 63 ++++-- packaging/windows/generatebundle.ps1 | 104 ++++++++++ packaging/windows/generatemsi.ps1 | 121 +----------- .../CurrentPlatform.cs | 37 ++++ .../Enumerations/BuildPlatform.cs | 10 +- .../StandardGoals.cs | 3 +- .../BuildPlatformsAttribute.cs | 9 +- .../TargetConditions/EnvironmentAttribute.cs | 37 ++++ scripts/dotnet-cli-build/InstallerTargets.cs | 51 +++++ scripts/dotnet-cli-build/MsiTargets.cs | 139 +++++++++++++ scripts/dotnet-cli-build/PackageTargets.cs | 138 +++++++++++++ scripts/dotnet-cli-build/PrepareTargets.cs | 37 +++- scripts/dotnet-cli-build/PublishTargets.cs | 167 ++++++++++------ scripts/dotnet-cli-build/Utils/Dirs.cs | 3 +- scripts/dotnet-cli-build/Utils/Monikers.cs | 35 ++++ scripts/dotnet-cli-build/project.json | 5 +- scripts/package/package-debian.sh | 3 - scripts/package/package-dnvm.sh | 38 ---- scripts/package/package-native.sh | 25 --- scripts/package/package-zip.ps1 | 44 ----- scripts/package/package.cmd | 6 - scripts/package/package.ps1 | 24 --- scripts/package/package.sh | 40 ---- scripts/publish/publish.ps1 | 186 ------------------ 25 files changed, 754 insertions(+), 577 deletions(-) create mode 100644 packaging/windows/generatebundle.ps1 create mode 100644 scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/EnvironmentAttribute.cs create mode 100644 scripts/dotnet-cli-build/InstallerTargets.cs create mode 100644 scripts/dotnet-cli-build/MsiTargets.cs create mode 100644 scripts/dotnet-cli-build/PackageTargets.cs create mode 100644 scripts/dotnet-cli-build/Utils/Monikers.cs delete mode 100755 scripts/package/package-dnvm.sh delete mode 100755 scripts/package/package-native.sh delete mode 100644 scripts/package/package-zip.ps1 delete mode 100644 scripts/package/package.cmd delete mode 100644 scripts/package/package.ps1 delete mode 100755 scripts/package/package.sh delete mode 100644 scripts/publish/publish.ps1 diff --git a/packaging/nuget/package.ps1 b/packaging/nuget/package.ps1 index 14b3b3385..b08fd21f3 100644 --- a/packaging/nuget/package.ps1 +++ b/packaging/nuget/package.ps1 @@ -13,8 +13,10 @@ if ($versionSuffix -ne "") { $versionArg = "--version-suffix" } -. "$PSScriptRoot\..\..\scripts\common\_common.ps1" -. "$REPOROOT\scripts\package\projectsToPack.ps1" +$RepoRoot = Convert-Path "$PSScriptRoot\..\.." + +. "$RepoRoot\scripts\common\_common.ps1" +. "$RepoRoot\scripts\package\projectsToPack.ps1" $IntermediatePackagesDir = "$RepoRoot\artifacts\packages\intermediate" $PackagesDir = "$RepoRoot\artifacts\packages" diff --git a/packaging/osx/package-osx.sh b/packaging/osx/package-osx.sh index e2a6a4ede..e767bcedb 100755 --- a/packaging/osx/package-osx.sh +++ b/packaging/osx/package-osx.sh @@ -12,26 +12,65 @@ while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symli done DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" -source "$DIR/../../scripts/common/_common.sh" +help(){ + echo "Usage: $0 [--version ] [--input ] [--output ] [--help]" + echo "" + echo "Options:" + echo " --version Specify a version for the package." + echo " --input Package the entire contents of the directory tree." + echo " --output The path to which the package will be written." + exit 1 +} + +while [[ $# > 0 ]]; do + lowerI="$(echo $1 | awk '{print tolower($0)}')" + case $lowerI in + -v|--version) + DOTNET_CLI_VERSION=$2 + shift + ;; + -o|--output) + OUTPUT_PKG=$2 + shift + ;; + -i|--input) + INPUT_DIR=$2 + shift + ;; + --help) + help + ;; + *) + break + ;; + esac + shift +done if [ -z "$DOTNET_CLI_VERSION" ]; then - echo "Provide a version number (DOTNET_CLI_VERSION) $DOTNET_CLI_VERSION" && exit 1 + echo "Provide a version number. Missing option '--version'" && help fi -STAGE2_DIR=$REPOROOT/artifacts/$RID/stage2 +if [ -z "$OUTPUT_PKG" ]; then + echo "Provide an output pkg. Missing option '--output'" && help +fi -if [ ! -d "$STAGE2_DIR" ]; then - echo "Missing stage2 output in $STAGE2_DIR" 1>&2 +if [ -z "$INPUT_DIR" ]; then + echo "Provide an inout directory. Missing option '--input'" && help +fi + +if [ ! -d "$INPUT_DIR" ]; then + echo "Missing input directory - $INPUT_DIR" 1>&2 exit 1 fi -PACKAGE_DIR=$REPOROOT/artifacts/packages/pkg +PACKAGE_DIR=$(dirname "${OUTPUT_PKG}") [ -d "$PACKAGE_DIR" ] || mkdir -p $PACKAGE_DIR -PACKAGE_ID=dotnet-osx-x64.${DOTNET_CLI_VERSION}.pkg -PACKAGE_NAME=$PACKAGE_DIR/$PACKAGE_ID -#chmod -R 755 $STAGE2_DIR -pkgbuild --root $STAGE2_DIR \ +PACKAGE_ID=$(basename "${OUTPUT_PKG}") + +#chmod -R 755 $INPUT_DIR +pkgbuild --root $INPUT_DIR \ --version $DOTNET_CLI_VERSION \ --scripts $DIR/scripts \ --identifier com.microsoft.dotnet.cli.pkg.dotnet-osx-x64 \ @@ -40,10 +79,8 @@ pkgbuild --root $STAGE2_DIR \ cat $DIR/Distribution-Template | sed "/{VERSION}/s//$DOTNET_CLI_VERSION/g" > $DIR/Dist -productbuild --version $DOTNET_CLI_VERSION --identifier com.microsoft.dotnet.cli --package-path $DIR --resources $DIR/resources --distribution $DIR/Dist $PACKAGE_NAME +productbuild --version $DOTNET_CLI_VERSION --identifier com.microsoft.dotnet.cli --package-path $DIR --resources $DIR/resources --distribution $DIR/Dist $OUTPUT_PKG #Clean temp files rm $DIR/$PACKAGE_ID rm $DIR/Dist - -$REPOROOT/scripts/publish/publish.sh $PACKAGE_NAME diff --git a/packaging/windows/generatebundle.ps1 b/packaging/windows/generatebundle.ps1 new file mode 100644 index 000000000..0b528bc13 --- /dev/null +++ b/packaging/windows/generatebundle.ps1 @@ -0,0 +1,104 @@ +# Copyright (c) .NET Foundation and contributors. All rights reserved. +# Licensed under the MIT license. See LICENSE file in the project root for full license information. + +param( + [Parameter(Mandatory=$true)][string]$DotnetMSIFile, + [Parameter(Mandatory=$true)][string]$DotnetBundleOutput, + [Parameter(Mandatory=$true)][string]$WixRoot +) + +. "$PSScriptRoot\..\..\scripts\common\_common.ps1" +$RepoRoot = Convert-Path "$PSScriptRoot\..\.." + +function RunCandleForBundle +{ + $result = $true + pushd "$WixRoot" + + Write-Host Running candle for bundle.. + $AuthWsxRoot = Join-Path $RepoRoot "packaging\windows" + + .\candle.exe -nologo ` + -dDotnetSrc="$inputDir" ` + -dMicrosoftEula="$RepoRoot\packaging\osx\resources\en.lproj\eula.rtf" ` + -dBuildVersion="$env:DOTNET_MSI_VERSION" ` + -dDisplayVersion="$env:DOTNET_CLI_VERSION" ` + -dReleaseSuffix="$env:ReleaseSuffix" ` + -dMsiSourcePath="$DotnetMSIFile" ` + -arch "$env:ARCHITECTURE" ` + -ext WixBalExtension.dll ` + -ext WixUtilExtension.dll ` + -ext WixTagExtension.dll ` + "$AuthWsxRoot\bundle.wxs" | Out-Host + + if($LastExitCode -ne 0) + { + $result = $false + Write-Host "Candle failed with exit code $LastExitCode." + } + + popd + return $result +} + +function RunLightForBundle +{ + $result = $true + pushd "$WixRoot" + + Write-Host Running light for bundle.. + $AuthWsxRoot = Join-Path $RepoRoot "packaging\windows" + + .\light.exe -nologo ` + -cultures:en-us ` + bundle.wixobj ` + -ext WixBalExtension.dll ` + -ext WixUtilExtension.dll ` + -ext WixTagExtension.dll ` + -b "$AuthWsxRoot" ` + -out $DotnetBundleOutput | Out-Host + + if($LastExitCode -ne 0) + { + $result = $false + Write-Host "Light failed with exit code $LastExitCode." + } + + popd + return $result +} + + +if(!(Test-Path $DotnetMSIFile)) +{ + throw "$DotnetMSIFile not found" +} + +Write-Host "Creating dotnet Bundle at $DotnetBundleOutput" + +if([string]::IsNullOrEmpty($WixRoot)) +{ + Exit -1 +} + +if(-Not (RunCandleForBundle)) +{ + Exit -1 +} + +if(-Not (RunLightForBundle)) +{ + Exit -1 +} + +if(!(Test-Path $DotnetBundleOutput)) +{ + throw "Unable to create the dotnet bundle." + Exit -1 +} + +Write-Host -ForegroundColor Green "Successfully created dotnet bundle - $DotnetBundleOutput" + +_ $RepoRoot\test\Installer\testmsi.ps1 @("$DotnetMSIFile") + +exit $LastExitCode diff --git a/packaging/windows/generatemsi.ps1 b/packaging/windows/generatemsi.ps1 index fa6671e9f..693e1396c 100644 --- a/packaging/windows/generatemsi.ps1 +++ b/packaging/windows/generatemsi.ps1 @@ -2,42 +2,17 @@ # Licensed under the MIT license. See LICENSE file in the project root for full license information. param( - [Parameter(Mandatory=$true)][string]$inputDir + [Parameter(Mandatory=$true)][string]$inputDir, + [Parameter(Mandatory=$true)][string]$DotnetMSIOutput, + [Parameter(Mandatory=$true)][string]$WixRoot ) . "$PSScriptRoot\..\..\scripts\common\_common.ps1" +$RepoRoot = Convert-Path "$PSScriptRoot\..\.." -$DotnetMSIOutput = "" -$DotnetBundleOutput = "" -$WixRoot = "" $InstallFileswsx = "install-files.wxs" $InstallFilesWixobj = "install-files.wixobj" -function AcquireWixTools -{ - $result = Join-Path $OutputDir WiXTools - - if(Test-Path "$result\candle.exe") - { - return $result - } - - Write-Host Downloading Wixtools.. - New-Item $result -type directory -force | Out-Null - # Download Wix version 3.10.2 - https://wix.codeplex.com/releases/view/619491 - Invoke-WebRequest -Uri https://wix.codeplex.com/downloads/get/1540241 -Method Get -OutFile $result\WixTools.zip - - Write-Host Extracting Wixtools.. - [System.IO.Compression.ZipFile]::ExtractToDirectory("$result\WixTools.zip", $result) - - if($LastExitCode -ne 0) - { - throw "Unable to download and extract the WixTools." - } - - return $result -} - function RunHeat { $result = $true @@ -121,65 +96,6 @@ function RunLight return $result } -function RunCandleForBundle -{ - $result = $true - pushd "$WixRoot" - - Write-Host Running candle for bundle.. - $AuthWsxRoot = Join-Path $RepoRoot "packaging\windows" - - .\candle.exe -nologo ` - -dDotnetSrc="$inputDir" ` - -dMicrosoftEula="$RepoRoot\packaging\osx\resources\en.lproj\eula.rtf" ` - -dBuildVersion="$env:DOTNET_MSI_VERSION" ` - -dDisplayVersion="$env:DOTNET_CLI_VERSION" ` - -dReleaseSuffix="$env:ReleaseSuffix" ` - -dMsiSourcePath="$DotnetMSIOutput" ` - -arch "$env:ARCHITECTURE" ` - -ext WixBalExtension.dll ` - -ext WixUtilExtension.dll ` - -ext WixTagExtension.dll ` - "$AuthWsxRoot\bundle.wxs" | Out-Host - - if($LastExitCode -ne 0) - { - $result = $false - Write-Host "Candle failed with exit code $LastExitCode." - } - - popd - return $result -} - -function RunLightForBundle -{ - $result = $true - pushd "$WixRoot" - - Write-Host Running light for bundle.. - $AuthWsxRoot = Join-Path $RepoRoot "packaging\windows" - - .\light.exe -nologo ` - -cultures:en-us ` - bundle.wixobj ` - -ext WixBalExtension.dll ` - -ext WixUtilExtension.dll ` - -ext WixTagExtension.dll ` - -b "$AuthWsxRoot" ` - -out $DotnetBundleOutput | Out-Host - - if($LastExitCode -ne 0) - { - $result = $false - Write-Host "Light failed with exit code $LastExitCode." - } - - popd - return $result -} - - if(!(Test-Path $inputDir)) { throw "$inputDir not found" @@ -190,14 +106,7 @@ if(!(Test-Path $PackageDir)) mkdir $PackageDir | Out-Null } -$DotnetMSIOutput = Join-Path $PackageDir "dotnet-win-$env:ARCHITECTURE.$env:DOTNET_CLI_VERSION.msi" -$DotnetBundleOutput = Join-Path $PackageDir "dotnet-win-$env:ARCHITECTURE.$env:DOTNET_CLI_VERSION.exe" - Write-Host "Creating dotnet MSI at $DotnetMSIOutput" -Write-Host "Creating dotnet Bundle at $DotnetBundleOutput" - -$WixRoot = AcquireWixTools - if([string]::IsNullOrEmpty($WixRoot)) { @@ -214,39 +123,17 @@ if(-Not (RunCandle)) Exit -1 } -if(-Not (RunCandleForBundle)) -{ - Exit -1 -} - if(-Not (RunLight)) { Exit -1 } -if(-Not (RunLightForBundle)) -{ - Exit -1 -} - if(!(Test-Path $DotnetMSIOutput)) { throw "Unable to create the dotnet msi." Exit -1 } -if(!(Test-Path $DotnetBundleOutput)) -{ - throw "Unable to create the dotnet bundle." - Exit -1 -} - Write-Host -ForegroundColor Green "Successfully created dotnet MSI - $DotnetMSIOutput" -Write-Host -ForegroundColor Green "Successfully created dotnet bundle - $DotnetBundleOutput" - -_ $RepoRoot\test\Installer\testmsi.ps1 @("$DotnetMSIOutput") - -$PublishScript = Join-Path $PSScriptRoot "..\..\scripts\publish\publish.ps1" -& $PublishScript -file $DotnetBundleOutput exit $LastExitCode diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/CurrentPlatform.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/CurrentPlatform.cs index fb70d37c1..45e1bb5cb 100644 --- a/scripts/Microsoft.DotNet.Cli.Build.Framework/CurrentPlatform.cs +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/CurrentPlatform.cs @@ -48,6 +48,43 @@ namespace Microsoft.DotNet.Cli.Build.Framework } } + public static bool IsUnix + { + get + { + return IsLinux || IsOSX; + } + } + + public static bool IsLinux + { + get + { + return IsUbuntu || IsCentOS; + } + } + + public static bool IsPlatform(BuildPlatform platform) + { + switch (platform) + { + case BuildPlatform.Windows: + return IsWindows; + case BuildPlatform.Ubuntu: + return IsUbuntu; + case BuildPlatform.OSX: + return IsOSX; + case BuildPlatform.CentOS: + return IsCentOS; + case BuildPlatform.Unix: + return IsUnix; + case BuildPlatform.Linux: + return IsLinux; + default: + throw new Exception("Unrecognized Platform."); + } + } + private static BuildPlatform DetermineCurrentPlatform() { if (IsWindows) diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/Enumerations/BuildPlatform.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/Enumerations/BuildPlatform.cs index d594ca604..a29a8aeaa 100644 --- a/scripts/Microsoft.DotNet.Cli.Build.Framework/Enumerations/BuildPlatform.cs +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/Enumerations/BuildPlatform.cs @@ -3,8 +3,10 @@ namespace Microsoft.DotNet.Cli.Build.Framework public enum BuildPlatform { Windows = 1, - OSX = 2, - Ubuntu = 3, - CentOS = 4 + Unix = 2, + Linux = 3, + OSX = 4, + Ubuntu = 5, + CentOS = 6 } -} \ No newline at end of file +} diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/StandardGoals.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/StandardGoals.cs index c22ac967a..975f1fa6f 100644 --- a/scripts/Microsoft.DotNet.Cli.Build.Framework/StandardGoals.cs +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/StandardGoals.cs @@ -11,10 +11,11 @@ namespace Microsoft.DotNet.Cli.Build.Framework { return self.UseTargets(new[] { - new BuildTarget("Default", "Standard Goals", new [] { "Prepare", "Compile", "Test", "Publish" }), + new BuildTarget("Default", "Standard Goals", new [] { "Prepare", "Compile", "Test", "Package", "Publish" }), new BuildTarget("Prepare", "Standard Goals"), new BuildTarget("Compile", "Standard Goals"), new BuildTarget("Test", "Standard Goals"), + new BuildTarget("Package", "Standard Goals"), new BuildTarget("Publish", "Standard Goals") }); } diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/BuildPlatformsAttribute.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/BuildPlatformsAttribute.cs index d05655a67..92e8f2441 100644 --- a/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/BuildPlatformsAttribute.cs +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/BuildPlatformsAttribute.cs @@ -20,16 +20,9 @@ namespace Microsoft.DotNet.Cli.Build.Framework public override bool EvaluateCondition() { - var currentPlatform = CurrentPlatform.Current; - - if (currentPlatform == default(BuildPlatform)) - { - throw new Exception("Unrecognized Platform."); - } - foreach (var platform in _buildPlatforms) { - if (platform == currentPlatform) + if (CurrentPlatform.IsPlatform(platform)) { return true; } diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/EnvironmentAttribute.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/EnvironmentAttribute.cs new file mode 100644 index 000000000..473aff2da --- /dev/null +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/EnvironmentAttribute.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; + +namespace Microsoft.DotNet.Cli.Build.Framework +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = false)] + public class EnvironmentAttribute : TargetConditionAttribute + { + private string _envVar; + private string _expectedVal; + + public EnvironmentAttribute(string envVar, string expectedVal) + { + if (string.IsNullOrEmpty(envVar)) + { + throw new ArgumentNullException("envVar"); + } + + _envVar = envVar; + _expectedVal = expectedVal; + } + + public override bool EvaluateCondition() + { + var actualVal = Environment.GetEnvironmentVariable(_envVar); + + if (string.IsNullOrEmpty(_expectedVal)) + { + return string.IsNullOrEmpty(actualVal) || + actualVal.Equals("0") || + actualVal.ToLower().Equals("false"); + } + + return _expectedVal.Equals(actualVal, StringComparison.Ordinal); + } + } +} diff --git a/scripts/dotnet-cli-build/InstallerTargets.cs b/scripts/dotnet-cli-build/InstallerTargets.cs new file mode 100644 index 000000000..81068ade0 --- /dev/null +++ b/scripts/dotnet-cli-build/InstallerTargets.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Runtime.InteropServices; +using Microsoft.DotNet.Cli.Build.Framework; +using Microsoft.Extensions.PlatformAbstractions; + +using static Microsoft.DotNet.Cli.Build.Framework.BuildHelpers; + +namespace Microsoft.DotNet.Cli.Build +{ + public class InstallerTargets + { + [Target(nameof(MsiTargets.GenerateMsis), + nameof(MsiTargets.GenerateBundle), + nameof(InstallerTargets.GeneratePkg), + nameof(InstallerTargets.GenerateDeb))] + public static BuildTargetResult GenerateInstaller(BuildTargetContext c) + { + return c.Success(); + } + + + + [Target] + [BuildPlatforms(BuildPlatform.OSX)] + public static BuildTargetResult GeneratePkg(BuildTargetContext c) + { + var version = c.BuildContext.Get("BuildVersion").SimpleVersion; + var pkg = c.BuildContext.Get("InstallerFile"); + Cmd(Path.Combine(Dirs.RepoRoot, "packaging", "osx", "package-osx.sh"), + "-v", version, "-i", Dirs.Stage2, "-o", pkg) + .Execute() + .EnsureSuccessful(); + return c.Success(); + } + + [Target] + [BuildPlatforms(BuildPlatform.Ubuntu)] + public static BuildTargetResult GenerateDeb(BuildTargetContext c) + { + var env = PackageTargets.GetCommonEnvVars(c); + Cmd(Path.Combine(Dirs.RepoRoot, "scripts", "package", "package-debian.sh")) + .Environment(env) + .Execute() + .EnsureSuccessful(); + return c.Success(); + } + } +} diff --git a/scripts/dotnet-cli-build/MsiTargets.cs b/scripts/dotnet-cli-build/MsiTargets.cs new file mode 100644 index 000000000..57120cdf5 --- /dev/null +++ b/scripts/dotnet-cli-build/MsiTargets.cs @@ -0,0 +1,139 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Runtime.InteropServices; +using Microsoft.DotNet.Cli.Build.Framework; +using Microsoft.Extensions.PlatformAbstractions; + +using static Microsoft.DotNet.Cli.Build.Framework.BuildHelpers; + +namespace Microsoft.DotNet.Cli.Build +{ + public class MsiTargets + { + private const string ENGINE = "engine.exe"; + + private static string WixRoot + { + get + { + return Path.Combine(Dirs.Output, "WixTools"); + } + } + + private static string Msi { get; set; } + + private static string Bundle { get; set; } + + private static string Engine { get; set; } + + private static void AcquireWix(BuildTargetContext c) + { + if (File.Exists(Path.Combine(WixRoot, "candle.exe"))) + { + return; + } + + Directory.CreateDirectory(WixRoot); + + c.Info("Downloading WixTools.."); + // Download Wix version 3.10.2 - https://wix.codeplex.com/releases/view/619491 + Cmd("powershell", "-NoProfile", "-NoLogo", + $"Invoke-WebRequest -Uri https://wix.codeplex.com/downloads/get/1540241 -Method Get -OutFile {WixRoot}\\WixTools.zip") + .Execute() + .EnsureSuccessful(); + + c.Info("Extracting WixTools.."); + ZipFile.ExtractToDirectory($"{WixRoot}\\WixTools.zip", WixRoot); + } + + [Target] + [BuildPlatforms(BuildPlatform.Windows)] + public static BuildTargetResult InitMsi(BuildTargetContext c) + { + Bundle = c.BuildContext.Get("InstallerFile"); + Msi = Path.ChangeExtension(Bundle, "msi"); + Engine = Path.Combine(Path.GetDirectoryName(Bundle), ENGINE); + AcquireWix(c); + return c.Success(); + } + + [Target(nameof(MsiTargets.InitMsi), + nameof(GenerateDotnetMuxerMsi), + nameof(GenerateDotnetSharedFxMsi), + nameof(GenerateCLISDKMsi))] + [BuildPlatforms(BuildPlatform.Windows)] + public static BuildTargetResult GenerateMsis(BuildTargetContext c) + { + var env = PackageTargets.GetCommonEnvVars(c); + Cmd("powershell", "-NoProfile", "-NoLogo", + Path.Combine(Dirs.RepoRoot, "packaging", "windows", "generatemsi.ps1"), Dirs.Stage2, Msi, WixRoot) + .Environment(env) + .Execute() + .EnsureSuccessful(); + return c.Success(); + } + + [Target] + [BuildPlatforms(BuildPlatform.Windows)] + public static BuildTargetResult GenerateCLISDKMsi(BuildTargetContext c) + { + var env = PackageTargets.GetCommonEnvVars(c); + Cmd("powershell", "-NoProfile", "-NoLogo", + Path.Combine(Dirs.RepoRoot, "packaging", "windows", "generatemsi.ps1"), Dirs.Stage2, Msi, WixRoot) + .Environment(env) + .Execute() + .EnsureSuccessful(); + return c.Success(); + } + + [Target] + [BuildPlatforms(BuildPlatform.Windows)] + public static BuildTargetResult GenerateDotnetMuxerMsi(BuildTargetContext c) + { + return c.Success(); + } + + [Target] + [BuildPlatforms(BuildPlatform.Windows)] + public static BuildTargetResult GenerateDotnetSharedFxMsi(BuildTargetContext c) + { + return c.Success(); + } + + + [Target(nameof(MsiTargets.InitMsi))] + [BuildPlatforms(BuildPlatform.Windows)] + public static BuildTargetResult GenerateBundle(BuildTargetContext c) + { + var env = PackageTargets.GetCommonEnvVars(c); + Cmd("powershell", "-NoProfile", "-NoLogo", + Path.Combine(Dirs.RepoRoot, "packaging", "windows", "generatebundle.ps1"), Msi, Bundle, WixRoot) + .Environment(env) + .Execute() + .EnsureSuccessful(); + return c.Success(); + } + + [Target(nameof(MsiTargets.InitMsi))] + [BuildPlatforms(BuildPlatform.Windows)] + public static BuildTargetResult ExtractEngineFromBundle(BuildTargetContext c) + { + Cmd($"{WixRoot}\\insignia.exe", "-ib", Bundle, "-o", Engine) + .Execute() + .EnsureSuccessful(); + return c.Success(); + } + + [Target(nameof(MsiTargets.InitMsi))] + [BuildPlatforms(BuildPlatform.Windows)] + public static BuildTargetResult ReattachEngineToBundle(BuildTargetContext c) + { + Cmd($"{WixRoot}\\insignia.exe", "-ab", Engine, Bundle, "-o", Bundle) + .Execute() + .EnsureSuccessful(); + return c.Success(); + } + } +} diff --git a/scripts/dotnet-cli-build/PackageTargets.cs b/scripts/dotnet-cli-build/PackageTargets.cs new file mode 100644 index 000000000..c0c369be2 --- /dev/null +++ b/scripts/dotnet-cli-build/PackageTargets.cs @@ -0,0 +1,138 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Runtime.InteropServices; +using Microsoft.DotNet.Cli.Build.Framework; +using Microsoft.Extensions.PlatformAbstractions; + +using static Microsoft.DotNet.Cli.Build.Framework.BuildHelpers; + +namespace Microsoft.DotNet.Cli.Build +{ + public static class PackageTargets + { + [Target] + public static BuildTargetResult InitPackage(BuildTargetContext c) + { + Directory.CreateDirectory(Dirs.Packages); + return c.Success(); + } + + [Target(nameof(PrepareTargets.Init), + nameof(PackageTargets.InitPackage), + nameof(PackageTargets.GenerateVersionBadge), + nameof(PackageTargets.GenerateCompressedFile), + nameof(InstallerTargets.GenerateInstaller), + nameof(PackageTargets.GenerateNugetPackages))] + [Environment("DOTNET_BUILD_SKIP_PACKAGING", null)] + public static BuildTargetResult Package(BuildTargetContext c) + { + return c.Success(); + } + + [Target] + public static BuildTargetResult GenerateVersionBadge(BuildTargetContext c) + { + var buildVersion = c.BuildContext.Get("BuildVersion"); + var versionSvg = Path.Combine(Dirs.RepoRoot, "resources", "images", "version_badge.svg"); + var outputVersionSvg = c.BuildContext.Get("VersionBadge"); + + var versionSvgContent = File.ReadAllText(versionSvg); + versionSvgContent = versionSvgContent.Replace("ver_number", buildVersion.SimpleVersion); + File.WriteAllText(outputVersionSvg, versionSvgContent); + + return c.Success(); + } + + [Target(nameof(PackageTargets.GenerateZip), nameof(PackageTargets.GenerateTarBall))] + public static BuildTargetResult GenerateCompressedFile(BuildTargetContext c) + { + return c.Success(); + } + + [Target(nameof(PackageTargets.InitPackage))] + [BuildPlatforms(BuildPlatform.Windows)] + public static BuildTargetResult GenerateZip(BuildTargetContext c) + { + var zipFile = c.BuildContext.Get("CompressedFile"); + + if (File.Exists(zipFile)) + { + File.Delete(zipFile); + } + + ZipFile.CreateFromDirectory(Dirs.Stage2, zipFile, CompressionLevel.Optimal, false); + return c.Success(); + } + + [Target(nameof(PackageTargets.InitPackage))] + [BuildPlatforms(BuildPlatform.Unix)] + public static BuildTargetResult GenerateTarBall(BuildTargetContext c) + { + var tarFile = c.BuildContext.Get("CompressedFile"); + + if (File.Exists(tarFile)) + { + File.Delete(tarFile); + } + + Cmd("tar", "-czf", tarFile, "-C", Dirs.Stage2, ".") + .Execute() + .EnsureSuccessful(); + return c.Success(); + } + + [Target] + [BuildPlatforms(BuildPlatform.Windows)] + public static BuildTargetResult GenerateNugetPackages(BuildTargetContext c) + { + var versionSuffix = c.BuildContext.Get("BuildVersion").VersionSuffix; + var env = GetCommonEnvVars(c); + Cmd("powershell", "-NoProfile", "-NoLogo", + Path.Combine(Dirs.RepoRoot, "packaging", "nuget", "package.ps1"), Path.Combine(Dirs.Stage2, "bin"), versionSuffix) + .Environment(env) + .Execute() + .EnsureSuccessful(); + return c.Success(); + } + + internal static Dictionary GetCommonEnvVars(BuildTargetContext c) + { + // Set up the environment variables previously defined by common.sh/ps1 + // This is overkill, but I want to cover all the variables used in all OSes (including where some have the same names) + var buildVersion = c.BuildContext.Get("BuildVersion"); + var configuration = c.BuildContext.Get("Configuration"); + var architecture = PlatformServices.Default.Runtime.RuntimeArchitecture; + var env = new Dictionary() + { + { "RID", PlatformServices.Default.Runtime.GetRuntimeIdentifier() }, + { "OSNAME", PlatformServices.Default.Runtime.OperatingSystem }, + { "TFM", "dnxcore50" }, + { "REPOROOT", Dirs.RepoRoot }, + { "OutputDir", Dirs.Output }, + { "Stage1Dir", Dirs.Stage1 }, + { "Stage1CompilationDir", Dirs.Stage1Compilation }, + { "Stage2Dir", Dirs.Stage2 }, + { "STAGE2_DIR", Dirs.Stage2 }, + { "Stage2CompilationDir", Dirs.Stage2Compilation }, + { "HostDir", Dirs.Corehost }, + { "PackageDir", Path.Combine(Dirs.Packages) }, // Legacy name + { "TestBinRoot", Dirs.TestOutput }, + { "TestPackageDir", Dirs.TestPackages }, + { "MajorVersion", buildVersion.Major.ToString() }, + { "MinorVersion", buildVersion.Minor.ToString() }, + { "PatchVersion", buildVersion.Patch.ToString() }, + { "CommitCountVersion", buildVersion.CommitCountString }, + { "COMMIT_COUNT_VERSION", buildVersion.CommitCountString }, + { "DOTNET_CLI_VERSION", buildVersion.SimpleVersion }, + { "DOTNET_MSI_VERSION", buildVersion.GenerateMsiVersion() }, + { "VersionSuffix", buildVersion.VersionSuffix }, + { "CONFIGURATION", configuration }, + { "ARCHITECTURE", architecture } + }; + + return env; + } + } +} diff --git a/scripts/dotnet-cli-build/PrepareTargets.cs b/scripts/dotnet-cli-build/PrepareTargets.cs index bc10066e9..801f15ac7 100644 --- a/scripts/dotnet-cli-build/PrepareTargets.cs +++ b/scripts/dotnet-cli-build/PrepareTargets.cs @@ -31,7 +31,7 @@ namespace Microsoft.DotNet.Cli.Build public static BuildTargetResult CheckInstallerBuildPlatformDependencies(BuildTargetContext c) => c.Success(); // All major targets will depend on this in order to ensure variables are set up right if they are run independently - [Target(nameof(GenerateVersions), nameof(CheckPrereqs), nameof(LocateStage0))] + [Target(nameof(GenerateVersions), nameof(CheckPrereqs), nameof(LocateStage0), nameof(ExpectedBuildArtifacts))] public static BuildTargetResult Init(BuildTargetContext c) { var runtimeInfo = PlatformServices.Default.Runtime; @@ -104,6 +104,41 @@ namespace Microsoft.DotNet.Cli.Build return c.Success(); } + [Target] + public static BuildTargetResult ExpectedBuildArtifacts(BuildTargetContext c) + { + var productName = Monikers.GetProductMoniker(c); + var config = Environment.GetEnvironmentVariable("CONFIGURATION"); + var versionBadgeName = $"{CurrentPlatform.Current}_{CurrentArchitecture.Current}_{config}_version_badge.svg"; + c.BuildContext["VersionBadge"] = Path.Combine(Dirs.Output, versionBadgeName); + + var extension = CurrentPlatform.IsWindows ? ".zip" : ".tar.gz"; + c.BuildContext["CompressedFile"] = Path.Combine(Dirs.Packages, productName + extension); + + string installer = ""; + switch(CurrentPlatform.Current) + { + case BuildPlatform.Windows: + installer = productName + ".exe"; + break; + case BuildPlatform.OSX: + installer = productName + ".pkg"; + break; + case BuildPlatform.Ubuntu: + installer = productName + ".deb"; + break; + default: + break; + } + + if(!string.IsNullOrEmpty(installer)) + { + c.BuildContext["InstallerFile"] = Path.Combine(Dirs.Packages, installer); + } + + return c.Success(); + } + [Target] public static BuildTargetResult CheckPackageCache(BuildTargetContext c) { diff --git a/scripts/dotnet-cli-build/PublishTargets.cs b/scripts/dotnet-cli-build/PublishTargets.cs index 2648461b6..df0309564 100644 --- a/scripts/dotnet-cli-build/PublishTargets.cs +++ b/scripts/dotnet-cli-build/PublishTargets.cs @@ -4,6 +4,10 @@ using System.IO; using System.Runtime.InteropServices; using Microsoft.DotNet.Cli.Build.Framework; using Microsoft.Extensions.PlatformAbstractions; +using Microsoft.WindowsAzure; +using Microsoft.WindowsAzure.Storage; +using Microsoft.WindowsAzure.Storage.Auth; +using Microsoft.WindowsAzure.Storage.Blob; using static Microsoft.DotNet.Cli.Build.Framework.BuildHelpers; @@ -11,71 +15,110 @@ namespace Microsoft.DotNet.Cli.Build { public static class PublishTargets { - [Target(nameof(PrepareTargets.Init))] + private static CloudBlobContainer BlobContainer { get; set; } + + private static string Channel { get; } = "Test";// Environment.GetEnvironmentVariable("RELEASE_SUFFIX"); + + private static string Version { get; set; } + + + [Target] + public static BuildTargetResult InitPublish(BuildTargetContext c) + { + CloudStorageAccount storageAccount = CloudStorageAccount.Parse(Environment.GetEnvironmentVariable("CONNECTION_STRING").Trim('"')); + CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient(); + BlobContainer = blobClient.GetContainerReference("dotnet"); + + Version = c.BuildContext.Get("BuildVersion").SimpleVersion; + return c.Success(); + } + + [Target(nameof(PrepareTargets.Init), + nameof(PublishTargets.InitPublish), + nameof(PublishTargets.PublishArtifacts))] + [Environment("PUBLISH_TO_AZURE_BLOB", "true")] // This is set by CI systems public static BuildTargetResult Publish(BuildTargetContext c) { - if (string.Equals(Environment.GetEnvironmentVariable("DOTNET_BUILD_SKIP_PACKAGING"), "1", StringComparison.Ordinal)) - { - c.Info("Skipping packaging because DOTNET_BUILD_SKIP_PACKAGING is set"); - return c.Success(); - } - - // NOTE(anurse): Currently, this just invokes the remaining build scripts as-is. We should port those to C# as well, but - // I want to get the merged in. - - // Set up the environment variables previously defined by common.sh/ps1 - // This is overkill, but I want to cover all the variables used in all OSes (including where some have the same names) - var buildVersion = c.BuildContext.Get("BuildVersion"); - var configuration = c.BuildContext.Get("Configuration"); - var architecture = PlatformServices.Default.Runtime.RuntimeArchitecture; - var env = new Dictionary() - { - { "RID", PlatformServices.Default.Runtime.GetRuntimeIdentifier() }, - { "OSNAME", PlatformServices.Default.Runtime.OperatingSystem }, - { "TFM", "netstandardapp1.5" }, - { "OutputDir", Dirs.Output }, - { "Stage1Dir", Dirs.Stage1 }, - { "Stage1CompilationDir", Dirs.Stage1Compilation }, - { "Stage2Dir", Dirs.Stage2 }, - { "STAGE2_DIR", Dirs.Stage2 }, - { "Stage2CompilationDir", Dirs.Stage2Compilation }, - { "HostDir", Dirs.Corehost }, - { "PackageDir", Path.Combine(Dirs.Packages, "dnvm") }, // Legacy name - { "TestBinRoot", Dirs.TestOutput }, - { "TestPackageDir", Dirs.TestPackages }, - { "MajorVersion", buildVersion.Major.ToString() }, - { "MinorVersion", buildVersion.Minor.ToString() }, - { "PatchVersion", buildVersion.Patch.ToString() }, - { "CommitCountVersion", buildVersion.CommitCountString }, - { "COMMIT_COUNT_VERSION", buildVersion.CommitCountString }, - { "DOTNET_CLI_VERSION", buildVersion.SimpleVersion }, - { "DOTNET_MSI_VERSION", buildVersion.GenerateMsiVersion() }, - { "VersionSuffix", buildVersion.VersionSuffix }, - { "CONFIGURATION", configuration }, - { "ARCHITECTURE", architecture } - }; - - if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - env["OSNAME"] = "osx"; - } - - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - Cmd("powershell", "-NoProfile", "-NoLogo", Path.Combine(c.BuildContext.BuildDirectory, "scripts", "package", "package.ps1")) - .Environment(env) - .Execute() - .EnsureSuccessful(); - } - else - { - // Can directly execute scripts on Unix :). Thank you shebangs! - Cmd(Path.Combine(c.BuildContext.BuildDirectory, "scripts", "package", "package.sh")) - .Environment(env) - .Execute() - .EnsureSuccessful(); - } return c.Success(); } + + [Target(nameof(PublishTargets.PublishVersionBadge), + nameof(PublishTargets.PublishCompressedFile), + nameof(PublishTargets.PublishInstallerFile), + nameof(PublishTargets.PublishLatestVersionTextFile))] + public static BuildTargetResult PublishArtifacts(BuildTargetContext c) + { + return c.Success(); + } + + [Target] + public static BuildTargetResult PublishVersionBadge(BuildTargetContext c) + { + var versionBadge = c.BuildContext.Get("VersionBadge"); + var latestVersionBadgeBlob = $"{Channel}/Binaries/Latest/{Path.GetFileName(versionBadge)}"; + var versionBadgeBlob = $"{Channel}/Binaries/{Version}/{Path.GetFileName(versionBadge)}"; + + PublishFileAzure(versionBadgeBlob, versionBadge); + PublishFileAzure(latestVersionBadgeBlob, versionBadge); + return c.Success(); + } + + [Target] + public static BuildTargetResult PublishCompressedFile(BuildTargetContext c) + { + var compressedFile = c.BuildContext.Get("CompressedFile"); + var compressedFileBlob = $"{Channel}/Binaries/{Version}/{Path.GetFileName(compressedFile)}"; + var latestCompressedFile = compressedFile.Replace(Version, "latest"); + var latestCompressedFileBlob = $"{Channel}/Binaries/Latest/{Path.GetFileName(latestCompressedFile)}"; + + PublishFileAzure(compressedFileBlob, compressedFile); + PublishFileAzure(latestCompressedFileBlob, compressedFile); + return c.Success(); + } + + [Target] + [BuildPlatforms(BuildPlatform.Windows, BuildPlatform.OSX, BuildPlatform.Ubuntu)] + public static BuildTargetResult PublishInstallerFile(BuildTargetContext c) + { + var installerFile = c.BuildContext.Get("InstallerFile"); + var installerFileBlob = $"{Channel}/Installers/{Version}/{Path.GetFileName(installerFile)}"; + var latestInstallerFile = installerFile.Replace(Version, "latest"); + var latestInstallerFileBlob = $"{Channel}/Installers/Latest/{Path.GetFileName(latestInstallerFile)}"; + + PublishFileAzure(installerFileBlob, installerFile); + PublishFileAzure(latestInstallerFileBlob, installerFile); + return c.Success(); + } + + [Target] + public static BuildTargetResult PublishLatestVersionTextFile(BuildTargetContext c) + { + var osname = Monikers.GetOSShortName(); + var latestVersionBlob = $"{Channel}/dnvm/latest.{osname}.{CurrentArchitecture.Current}.version"; + var latestVersionFile = Path.Combine(Dirs.Stage2, ".version"); + + PublishFileAzure(latestVersionBlob, latestVersionFile); + return c.Success(); + } + + private static BuildTargetResult PublishFile(BuildTargetContext c, string file) + { + var env = PackageTargets.GetCommonEnvVars(c); + Cmd("powershell", "-NoProfile", "-NoLogo", + Path.Combine(Dirs.RepoRoot, "scripts", "publish", "publish.ps1"), file) + .Environment(env) + .Execute() + .EnsureSuccessful(); + return c.Success(); + } + + private static void PublishFileAzure(string blob, string file) + { + CloudBlockBlob blockBlob = BlobContainer.GetBlockBlobReference(blob); + using (var fileStream = File.OpenRead(file)) + { + blockBlob.UploadFromStreamAsync(fileStream).Wait(); + } + } } } diff --git a/scripts/dotnet-cli-build/Utils/Dirs.cs b/scripts/dotnet-cli-build/Utils/Dirs.cs index 98ee39fc1..eea866d9b 100644 --- a/scripts/dotnet-cli-build/Utils/Dirs.cs +++ b/scripts/dotnet-cli-build/Utils/Dirs.cs @@ -7,8 +7,9 @@ namespace Microsoft.DotNet.Cli.Build { public static class Dirs { + public static readonly string RepoRoot = Directory.GetCurrentDirectory(); public static readonly string Output = Path.Combine( - Directory.GetCurrentDirectory(), + RepoRoot, "artifacts", PlatformServices.Default.Runtime.GetRuntimeIdentifier()); public static readonly string Packages = Path.Combine(Output, "packages"); diff --git a/scripts/dotnet-cli-build/Utils/Monikers.cs b/scripts/dotnet-cli-build/Utils/Monikers.cs new file mode 100644 index 000000000..0940a40d6 --- /dev/null +++ b/scripts/dotnet-cli-build/Utils/Monikers.cs @@ -0,0 +1,35 @@ +using Microsoft.DotNet.Cli.Build.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.DotNet.Cli.Build +{ + public class Monikers + { + public static string GetProductMoniker(BuildTargetContext c) + { + string osname = GetOSShortName(); + var arch = CurrentArchitecture.Current.ToString(); + var version = c.BuildContext.Get("BuildVersion").SimpleVersion; + return $"dotnet-{osname}-{arch}.{version}"; + } + + public static string GetOSShortName() + { + string osname = ""; + switch (CurrentPlatform.Current) + { + case BuildPlatform.Windows: + osname = "win"; + break; + default: + osname = CurrentPlatform.Current.ToString().ToLower(); + break; + } + + return osname; + } + } +} diff --git a/scripts/dotnet-cli-build/project.json b/scripts/dotnet-cli-build/project.json index 7b6298d22..e76a7a1c3 100755 --- a/scripts/dotnet-cli-build/project.json +++ b/scripts/dotnet-cli-build/project.json @@ -9,12 +9,13 @@ "NETStandard.Library": "1.0.0-rc2-23901", "System.IO.Compression.ZipFile": "4.0.1-rc2-23901", "Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-16537", - "Microsoft.DotNet.Cli.Build.Framework": "1.0.0-*" + "Microsoft.DotNet.Cli.Build.Framework": "1.0.0-*", + "WindowsAzure.Storage" : "6.2.2-preview" }, "frameworks": { "netstandardapp1.5": { - "imports": "dnxcore50" + "imports": ["dnxcore50", "portable-net45+win8"] } } } diff --git a/scripts/package/package-debian.sh b/scripts/package/package-debian.sh index 909f929e7..0db47aca6 100755 --- a/scripts/package/package-debian.sh +++ b/scripts/package/package-debian.sh @@ -141,6 +141,3 @@ execute_build DEBIAN_FILE=$(find $PACKAGE_OUTPUT_DIR -iname "*.deb") execute_test - -# Publish -$REPOROOT/scripts/publish/publish.sh $DEBIAN_FILE diff --git a/scripts/package/package-dnvm.sh b/scripts/package/package-dnvm.sh deleted file mode 100755 index 47d8fe396..000000000 --- a/scripts/package/package-dnvm.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright (c) .NET Foundation and contributors. All rights reserved. -# Licensed under the MIT license. See LICENSE file in the project root for full license information. -# - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -source "$DIR/../common/_common.sh" - -if [ ! -d "$STAGE2_DIR" ]; then - error "missing stage2 output in $STAGE2_DIR" 1>&2 - exit -fi - -PACKAGE_DIR=$REPOROOT/artifacts/packages/dnvm -[ -d "$PACKAGE_DIR" ] || mkdir -p $PACKAGE_DIR - -PACKAGE_SHORT_NAME=dotnet-${OSNAME}-x64.${DOTNET_CLI_VERSION} -PACKAGE_NAME=$PACKAGE_DIR/${PACKAGE_SHORT_NAME}.tar.gz - -cd $STAGE2_DIR - -header "Packaging $PACKAGE_SHORT_NAME" - -# Tar up the stage2 artifacts -# We need both "*" and ".version" to ensure we pick up that file -tar -czf $PACKAGE_NAME * .version - -info "Packaged stage2 from '$STAGE2_DIR' to '$PACKAGE_NAME'" - -$REPOROOT/scripts/publish/publish.sh $PACKAGE_NAME diff --git a/scripts/package/package-native.sh b/scripts/package/package-native.sh deleted file mode 100755 index f62754e8e..000000000 --- a/scripts/package/package-native.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright (c) .NET Foundation and contributors. All rights reserved. -# Licensed under the MIT license. See LICENSE file in the project root for full license information. -# - -set -e - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -source "$DIR/../common/_common.sh" - -if [[ "$OSNAME" == "ubuntu" ]]; then - # Create Debian package - $REPOROOT/scripts/package/package-debian.sh -elif [[ "$OSNAME" == "osx" ]]; then - # Create OSX PKG - $REPOROOT/packaging/osx/package-osx.sh -fi diff --git a/scripts/package/package-zip.ps1 b/scripts/package/package-zip.ps1 deleted file mode 100644 index 8b7000d65..000000000 --- a/scripts/package/package-zip.ps1 +++ /dev/null @@ -1,44 +0,0 @@ -# -# Copyright (c) .NET Foundation and contributors. All rights reserved. -# Licensed under the MIT license. See LICENSE file in the project root for full license information. -# - -. "$PSScriptRoot\..\common\_common.ps1" - -if(!(Test-Path $PackageDir)) { - mkdir $PackageDir | Out-Null -} - -if(![string]::IsNullOrEmpty($env:DOTNET_CLI_VERSION)) { - $PackageVersion = $env:DOTNET_CLI_VERSION -} else { - $Timestamp = [DateTime]::Now.ToString("yyyyMMddHHmmss") - $PackageVersion = "0.0.1-dev-t$Timestamp" -} - -# Stamp the output with the commit metadata and version number -$Commit = git rev-parse HEAD - -$VersionContent = @" -$Commit -$PackageVersion -"@ - -$VersionContent | Out-File -Encoding UTF8 "$Stage2Dir\.version" - -$PackageName = Join-Path $PackageDir "dotnet-win-$env:ARCHITECTURE.$PackageVersion.zip" - -if (Test-Path $PackageName) -{ - del $PackageName -} - -Add-Type -Assembly System.IO.Compression.FileSystem -[System.IO.Compression.ZipFile]::CreateFromDirectory($Stage2Dir, $PackageName, "Optimal", $false) - -Write-Host "Packaged stage2 to $PackageName" - -$PublishScript = Join-Path $PSScriptRoot "..\publish\publish.ps1" -& $PublishScript -file $PackageName - -exit $LastExitCode diff --git a/scripts/package/package.cmd b/scripts/package/package.cmd deleted file mode 100644 index 01f78b1ca..000000000 --- a/scripts/package/package.cmd +++ /dev/null @@ -1,6 +0,0 @@ -@echo off - -REM Copyright (c) .NET Foundation and contributors. All rights reserved. -REM Licensed under the MIT license. See LICENSE file in the project root for full license information. - -powershell -NoProfile -NoLogo -Command "%~dp0package.ps1 %*; exit $LastExitCode;" diff --git a/scripts/package/package.ps1 b/scripts/package/package.ps1 deleted file mode 100644 index cfb3c13d8..000000000 --- a/scripts/package/package.ps1 +++ /dev/null @@ -1,24 +0,0 @@ -# -# Copyright (c) .NET Foundation and contributors. All rights reserved. -# Licensed under the MIT license. See LICENSE file in the project root for full license information. -# - -. "$PSScriptRoot\..\common\_common.ps1" - -$RepoRoot = Convert-Path "$PSScriptRoot\..\.." - -header "Generating zip package" -_ "$RepoRoot\scripts\package\package-zip.ps1" - -header "Generating dotnet MSI" -_ "$RepoRoot\packaging\windows\generatemsi.ps1" @("$Stage2Dir") - -header "Generating NuGet packages" -_ "$RepoRoot\packaging\nuget\package.ps1" @("$Stage2Dir\bin", "$env:VersionSuffix") - -header "Generating version badge" -$VersionBadge = "$RepoRoot\resources\images\version_badge.svg" -$BadgeDestination = "$RepoRoot\artifacts\version_badge.svg" -(get-content $VersionBadge).replace("ver_number", "$env:DOTNET_CLI_VERSION") | set-content $BadgeDestination - -& "$RepoRoot\scripts\publish\publish.ps1" -file $BadgeDestination diff --git a/scripts/package/package.sh b/scripts/package/package.sh deleted file mode 100755 index 6b8e3c8d6..000000000 --- a/scripts/package/package.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright (c) .NET Foundation and contributors. All rights reserved. -# Licensed under the MIT license. See LICENSE file in the project root for full license information. -# - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -export REPOROOT="$(cd -P "$DIR/../.." && pwd)" - -set -e - -source "$DIR/../common/_common.sh" - -if [ -z "$DOTNET_CLI_VERSION" ]; then - TIMESTAMP=$(date "+%Y%m%d%H%M%S") - DOTNET_CLI_VERSION=0.0.1-dev-t$TIMESTAMP -fi - -VERSION_BADGE="$REPOROOT/resources/images/version_badge.svg" -BADGE_DESTINATION="$REPOROOT/artifacts/version_badge.svg" - -header "Generating tarball" -$DIR/package-dnvm.sh - -header "Generating Native Installer" -$DIR/package-native.sh - -header "Generating version badge" -sed "s/ver_number/$DOTNET_CLI_VERSION/g" $VERSION_BADGE > $BADGE_DESTINATION - -header "Publishing version badge" -$DIR/../publish/publish.sh $BADGE_DESTINATION - diff --git a/scripts/publish/publish.ps1 b/scripts/publish/publish.ps1 deleted file mode 100644 index 7c106f0bc..000000000 --- a/scripts/publish/publish.ps1 +++ /dev/null @@ -1,186 +0,0 @@ -# -# Copyright (c) .NET Foundation and contributors. All rights reserved. -# Licensed under the MIT license. See LICENSE file in the project root for full license information. -# - -param( - [Parameter(Mandatory=$true)][string]$file -) - -. "$PSScriptRoot\..\common\_common.ps1" - -function CheckRequiredVariables -{ - if([string]::IsNullOrEmpty($env:DOTNET_CLI_VERSION)) - { - return $false - } - - # this variable is set by the CI system - if([string]::IsNullOrEmpty($env:SASTOKEN)) - { - return $false - } - - # this variable is set by the CI system - if([string]::IsNullOrEmpty($env:STORAGE_ACCOUNT)) - { - return $false - } - - # this variable is set by the CI system - if([string]::IsNullOrEmpty($env:STORAGE_CONTAINER)) - { - return $false - } - - # this variable is set by the CI system - if([string]::IsNullOrEmpty($env:CHANNEL)) - { - return $false - } - - # this variable is set by the CI system - if([string]::IsNullOrEmpty($env:CONNECTION_STRING)) - { - return $false - } - - return $true -} - -function UploadFile($Blob, $Uploadfile, $PreventCaching = $false) -{ - Write-Host "Uploading $Uploadfile to dotnet feed." - - if([string]::IsNullOrEmpty($env:HOME)) - { - $env:HOME=Get-Location - } - - $properties = "" - - if($PreventCaching) - { - # use azure cli to upload to blob storage. We cannot use Invoke-WebRequest to do this becuase azure has a max limit of 64mb that can be uploaded using REST - #$statusCode = (Invoke-WebRequest -URI "$Upload_URI" -Method PUT -Headers @{"x-ms-blob-type"="BlockBlob"; "x-ms-date"="2015-10-23";"x-ms-version"="2013-08-15"} -InFile $Uploadfile).StatusCode - azure storage blob upload --quiet --properties cacheControl=no-cache --container $env:STORAGE_CONTAINER --blob $Blob --blobtype block --connection-string "$env:CONNECTION_STRING" --file $Uploadfile | Out-Host - } - else - { - # use azure cli to upload to blob storage. We cannot use Invoke-WebRequest to do this becuase azure has a max limit of 64mb that can be uploaded using REST - #$statusCode = (Invoke-WebRequest -URI "$Upload_URI" -Method PUT -Headers @{"x-ms-blob-type"="BlockBlob"; "x-ms-date"="2015-10-23";"x-ms-version"="2013-08-15"} -InFile $Uploadfile).StatusCode - azure storage blob upload --quiet $properties --container $env:STORAGE_CONTAINER --blob $Blob --blobtype block --connection-string "$env:CONNECTION_STRING" --file $Uploadfile | Out-Host - } - - - if($?) - { - Write-Host "Successfully uploaded $Uploadfile to dotnet feed." - return $true - } - else - { - Write-Host "Failed to upload $Uploadfile to dotnet feed." - return $false - } -} - -function UploadBinaries($zipFile) -{ - $result = -1 - $fileName = [System.IO.Path]::GetFileName($zipFile) - $zipBlob = "$env:CHANNEL/Binaries/$env:DOTNET_CLI_VERSION/$fileName" - - if(-Not (UploadFile $zipBlob $zipFile)) - { - return -1 - } - - Write-Host "Updating the latest dotnet binaries for windows.." - $zipBlobLatest = "$env:CHANNEL/Binaries/Latest/dotnet-win-$env:ARCHITECTURE.latest.zip" - - if(-Not (UploadFile $zipBlobLatest $zipFile $true)) - { - return -1 - } - - # update the version file - $versionFile = Convert-Path $PSScriptRoot\..\..\artifacts\$env:RID\stage2\.version - $versionBlob = "$env:CHANNEL/dnvm/latest.win.$env:ARCHITECTURE.version" - - if(-Not (UploadFile $versionBlob $versionFile $true)) - { - return -1 - } - - return 0 -} - -function UploadInstallers($installerFile) -{ - $fileName = [System.IO.Path]::GetFileName($installerFile) - $installerBlob = "$env:CHANNEL/Installers/$env:DOTNET_CLI_VERSION/$fileName" - - if(-Not (UploadFile $installerBlob $installerFile)) - { - return -1 - } - - Write-Host "Updating the latest dotnet installer for windows.." - $installerBlobLatest = "$env:CHANNEL/Installers/Latest/dotnet-win-$env:ARCHITECTURE.latest.exe" - - if(-Not (UploadFile $installerBlobLatest $installerFile $true)) - { - return -1 - } - - return 0 -} - -function UploadVersionBadge($badgeFile) -{ - $fileName = "windows_$($env:CONFIGURATION)_$([System.IO.Path]::GetFileName($badgeFile))" - - Write-Host "Uploading the version badge to Latest" - if(-Not (UploadFile "$env:CHANNEL/Binaries/Latest/$fileName" $badgeFile $true)) - { - return -1 - } - - Write-Host "Uploading the version badge to $env:DOTNET_CLI_VERSION" - if(-Not (UploadFile "$env:CHANNEL/Binaries/$env:DOTNET_CLI_VERSION/$fileName" $badgeFile)) - { - return -1 - } - - return 0 -} - -if(!(CheckRequiredVariables)) -{ - # fail silently if the required variables are not available for publishing the file - exit 0 -} - -if(![System.IO.File]::Exists($file)) -{ - throw "$file not found" -} - -$result = $false - -if([System.IO.Path]::GetExtension($file).ToLower() -eq ".zip") -{ - $result = UploadBinaries $file -} -elseif([System.IO.Path]::GetExtension($file).ToLower() -eq ".exe") -{ - $result = UploadInstallers $file -} -elseif ([System.IO.Path]::GetExtension($file).ToLower() -eq ".svg") -{ - $result = UploadVersionBadge $file -} - -exit $result From 6705585a67aa343bf6a3f5a3988044190c32d029 Mon Sep 17 00:00:00 2001 From: Livar Cunha Date: Mon, 7 Mar 2016 14:55:39 -0800 Subject: [PATCH 03/31] Updating test projects to the lastest version of dotnet-test-xunit runner. --- test/EndToEnd/project.json | 2 +- test/Microsoft.DotNet.ProjectModel.Tests/project.json | 2 +- test/Microsoft.DotNet.Tools.Tests.Utilities/project.json | 2 +- test/Microsoft.Extensions.DependencyModel.Tests/project.json | 3 +-- test/dotnet-build.Tests/project.json | 4 ++-- test/dotnet-compile.Tests/project.json | 2 +- test/dotnet-compile.UnitTests/project.json | 2 +- test/dotnet-projectmodel-server.Tests/project.json | 2 +- test/dotnet-publish.Tests/project.json | 2 +- test/dotnet-test.UnitTests/project.json | 2 +- test/dotnet.Tests/project.json | 2 +- 11 files changed, 12 insertions(+), 13 deletions(-) diff --git a/test/EndToEnd/project.json b/test/EndToEnd/project.json index 93c7084d9..4bcbd9290 100644 --- a/test/EndToEnd/project.json +++ b/test/EndToEnd/project.json @@ -14,7 +14,7 @@ "xunit": "2.1.0", "xunit.netcore.extensions": "1.0.0-prerelease-*", - "dotnet-test-xunit": "1.0.0-dev-79755-47" + "dotnet-test-xunit": "1.0.0-dev-91790-12" }, "frameworks": { diff --git a/test/Microsoft.DotNet.ProjectModel.Tests/project.json b/test/Microsoft.DotNet.ProjectModel.Tests/project.json index 0a33d56a1..edaaef649 100644 --- a/test/Microsoft.DotNet.ProjectModel.Tests/project.json +++ b/test/Microsoft.DotNet.ProjectModel.Tests/project.json @@ -6,7 +6,7 @@ "Microsoft.DotNet.ProjectModel": { "target": "project" }, "Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" }, "xunit": "2.1.0", - "dotnet-test-xunit": "1.0.0-dev-79755-47" + "dotnet-test-xunit": "1.0.0-dev-91790-12" }, "frameworks": { "netstandardapp1.5": { diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/project.json b/test/Microsoft.DotNet.Tools.Tests.Utilities/project.json index 535f5b902..cf42e619c 100644 --- a/test/Microsoft.DotNet.Tools.Tests.Utilities/project.json +++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/project.json @@ -10,7 +10,7 @@ "System.IO.Compression": "4.1.0-rc2-23901", "FluentAssertions": "4.0.0", "xunit": "2.1.0", - "dotnet-test-xunit": "1.0.0-dev-79755-47", + "dotnet-test-xunit": "1.0.0-dev-91790-12", "Microsoft.DotNet.TestFramework": "1.0.0-*", "Microsoft.DotNet.Cli.Utils": "1.0.0-*", diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/project.json b/test/Microsoft.Extensions.DependencyModel.Tests/project.json index cb583becc..18a43cf55 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/project.json +++ b/test/Microsoft.Extensions.DependencyModel.Tests/project.json @@ -12,7 +12,7 @@ "FluentAssertions": "4.0.0", "moq.netcore": "4.4.0-beta8", "xunit": "2.1.0", - "dotnet-test-xunit": "1.0.0-dev-79755-47" + "dotnet-test-xunit": "1.0.0-dev-91790-12" }, "frameworks": { @@ -24,6 +24,5 @@ } }, - "testRunner": "xunit" } \ No newline at end of file diff --git a/test/dotnet-build.Tests/project.json b/test/dotnet-build.Tests/project.json index 00afd26c1..c158034ef 100644 --- a/test/dotnet-build.Tests/project.json +++ b/test/dotnet-build.Tests/project.json @@ -1,6 +1,6 @@ { "version": "1.0.0-*", - + "dependencies": { "NETStandard.Library": "1.0.0-rc2-23901", "System.IO.Compression": "4.1.0-rc2-23901", @@ -11,7 +11,7 @@ }, "xunit": "2.1.0", - "dotnet-test-xunit": "1.0.0-dev-79755-47" + "dotnet-test-xunit": "1.0.0-dev-91790-12" }, "frameworks": { diff --git a/test/dotnet-compile.Tests/project.json b/test/dotnet-compile.Tests/project.json index 83f842a88..dd02d8697 100644 --- a/test/dotnet-compile.Tests/project.json +++ b/test/dotnet-compile.Tests/project.json @@ -11,7 +11,7 @@ }, "xunit": "2.1.0", - "dotnet-test-xunit": "1.0.0-dev-79755-47" + "dotnet-test-xunit": "1.0.0-dev-91790-12" }, "frameworks": { diff --git a/test/dotnet-compile.UnitTests/project.json b/test/dotnet-compile.UnitTests/project.json index 0208dc29c..9813a2d85 100644 --- a/test/dotnet-compile.UnitTests/project.json +++ b/test/dotnet-compile.UnitTests/project.json @@ -13,7 +13,7 @@ "Microsoft.DotNet.ProjectModel": { "target": "project" }, "xunit": "2.1.0", - "dotnet-test-xunit": "1.0.0-dev-79755-47", + "dotnet-test-xunit": "1.0.0-dev-91790-12", "moq.netcore": "4.4.0-beta8", "FluentAssertions": "4.2.2" }, diff --git a/test/dotnet-projectmodel-server.Tests/project.json b/test/dotnet-projectmodel-server.Tests/project.json index bbdf75c63..42d8fd6f6 100644 --- a/test/dotnet-projectmodel-server.Tests/project.json +++ b/test/dotnet-projectmodel-server.Tests/project.json @@ -4,7 +4,7 @@ "Microsoft.DotNet.ProjectModel": { "target": "project" }, "Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" }, "xunit": "2.1.0", - "dotnet-test-xunit": "1.0.0-dev-79755-47", + "dotnet-test-xunit": "1.0.0-dev-91790-12", "System.Net.NameResolution": "4.0.0-rc2-23901" }, diff --git a/test/dotnet-publish.Tests/project.json b/test/dotnet-publish.Tests/project.json index ab16338b8..0064f9349 100644 --- a/test/dotnet-publish.Tests/project.json +++ b/test/dotnet-publish.Tests/project.json @@ -13,7 +13,7 @@ "xunit": "2.1.0", "xunit.netcore.extensions": "1.0.0-prerelease-*", - "dotnet-test-xunit": "1.0.0-dev-79755-47" + "dotnet-test-xunit": "1.0.0-dev-91790-12" }, "frameworks": { diff --git a/test/dotnet-test.UnitTests/project.json b/test/dotnet-test.UnitTests/project.json index 1aa86bcd6..eb23b1792 100644 --- a/test/dotnet-test.UnitTests/project.json +++ b/test/dotnet-test.UnitTests/project.json @@ -8,7 +8,7 @@ "dotnet": { "target": "project" }, "xunit": "2.1.0", - "dotnet-test-xunit": "1.0.0-dev-79755-47", + "dotnet-test-xunit": "1.0.0-dev-91790-12", "moq.netcore": "4.4.0-beta8", "FluentAssertions": "4.2.2" }, diff --git a/test/dotnet.Tests/project.json b/test/dotnet.Tests/project.json index f6266f4ae..46da798d1 100644 --- a/test/dotnet.Tests/project.json +++ b/test/dotnet.Tests/project.json @@ -12,7 +12,7 @@ }, "xunit": "2.1.0", - "dotnet-test-xunit": "1.0.0-dev-79755-47" + "dotnet-test-xunit": "1.0.0-dev-91790-12" }, "frameworks": { From 53fd6075845a11a2760bfeed1a4f4c4426fd34fe Mon Sep 17 00:00:00 2001 From: Sridhar Periyasamy Date: Mon, 7 Mar 2016 20:23:41 -0500 Subject: [PATCH 04/31] Fix EndToEnd tests for RHEL. --- test/EndToEnd/EndToEndTest.cs | 63 ++++++++++++----------------------- 1 file changed, 21 insertions(+), 42 deletions(-) diff --git a/test/EndToEnd/EndToEndTest.cs b/test/EndToEnd/EndToEndTest.cs index f6f5663be..5fb8edccc 100644 --- a/test/EndToEnd/EndToEndTest.cs +++ b/test/EndToEnd/EndToEndTest.cs @@ -83,15 +83,8 @@ namespace Microsoft.DotNet.Tests.EndToEnd [Fact] public void TestDotnetBuildNativeRyuJit() { - if(IsCentOSorRHEL()) + if(!IsNativeCompilationSupported()) { - Console.WriteLine("Skipping native compilation tests on CentOS/RHEL - https://github.com/dotnet/cli/issues/453"); - return; - } - - if (IsWinX86()) - { - Console.WriteLine("Skipping native compilation tests on Windows x86 - https://github.com/dotnet/cli/issues/1550"); return; } @@ -105,15 +98,8 @@ namespace Microsoft.DotNet.Tests.EndToEnd [Fact] public void TestDotnetBuildNativeCpp() { - if(IsCentOSorRHEL()) - { - Console.WriteLine("Skipping native compilation tests on CentOS/RHEL - https://github.com/dotnet/cli/issues/453"); - return; - } - - if (IsWinX86()) - { - Console.WriteLine("Skipping native compilation tests on Windows x86 - https://github.com/dotnet/cli/issues/1550"); + if(!IsNativeCompilationSupported()) + { return; } @@ -127,15 +113,8 @@ namespace Microsoft.DotNet.Tests.EndToEnd [Fact] public void TestDotnetCompileNativeCppIncremental() { - if (IsCentOSorRHEL()) - { - Console.WriteLine("Skipping native compilation tests on CentOS/RHEL - https://github.com/dotnet/cli/issues/453"); - return; - } - - if (IsWinX86()) - { - Console.WriteLine("Skipping native compilation tests on Windows x86 - https://github.com/dotnet/cli/issues/1550"); + if(!IsNativeCompilationSupported()) + { return; } @@ -236,26 +215,26 @@ namespace Microsoft.DotNet.Tests.EndToEnd Directory.SetCurrentDirectory(currentDirectory); } - private bool IsCentOSorRHEL() + private bool IsNativeCompilationSupported() { - if(RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + bool isSupported = true; + var platform = PlatformServices.Default.Runtime.OperatingSystem.ToLower(); + switch (platform) { - const string OSIDFILE = "/etc/os-release"; - - if(File.Exists(OSIDFILE)) - { - string osidcontent = File.ReadAllText(OSIDFILE).ToLower(); - return osidcontent.Contains("centos") || osidcontent.Contains("rhel"); - } + case "centos": + case "rhel": + Console.WriteLine("Skipping native compilation tests on CentOS/RHEL - https://github.com/dotnet/cli/issues/453"); + isSupported = false; + break; + case "windows": + Console.WriteLine("Skipping native compilation tests on Windows x86 - https://github.com/dotnet/cli/issues/1550"); + isSupported = RuntimeInformation.ProcessArchitecture != Architecture.X86; + break; + default: + break; } - return false; - } - - private bool IsWinX86() - { - return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && - RuntimeInformation.ProcessArchitecture == Architecture.X86; + return isSupported; } private static DateTime GetLastWriteTimeUtcOfDirectoryFiles(string outputDirectory) From a0db5086f6283ca91bc676fdc36d509488c8b8c9 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Tue, 8 Mar 2016 09:22:17 -0800 Subject: [PATCH 05/31] Fix dependency context builder regression --- .../DependencyContextBuilder.cs | 2 +- .../DependencyContextBuilderTests.cs | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs b/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs index da9ad8444..b7eab17a4 100644 --- a/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs +++ b/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs @@ -84,7 +84,7 @@ namespace Microsoft.Extensions.DependencyModel var type = export.Library.Identity.Type; var serviceable = (export.Library as PackageDescription)?.Library.IsServiceable ?? false; - var libraryDependencies = new List(); + var libraryDependencies = new HashSet(); var libraryAssets = runtime ? export.RuntimeAssemblies : export.CompilationAssemblies; diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs index 13eaefaa0..ac336d97c 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs @@ -135,6 +135,34 @@ namespace Microsoft.Extensions.DependencyModel.Tests asm.Assemblies.Should().OnlyContain(l => l.Path == "System.Collections.dll"); } + [Fact] + public void FiltersDuplicatedDependencies() + { + var context = Build(runtimeExports: new[] + { + Export(PackageDescription("Pack.Age", + dependencies: new[] + { + new LibraryRange("System.Collections", + new VersionRange(new NuGetVersion(2, 0, 0)), + LibraryType.ReferenceAssembly, + LibraryDependencyType.Default), + new LibraryRange("System.Collections", + new VersionRange(new NuGetVersion(2, 1, 2)), + LibraryType.Package, + LibraryDependencyType.Default) + }) + ), + Export(ReferenceAssemblyDescription("System.Collections", + version: new NuGetVersion(2, 0, 0))) + }); + + context.RuntimeLibraries.Should().HaveCount(2); + + var lib = context.RuntimeLibraries.Should().Contain(l => l.Name == "Pack.Age").Subject; + lib.Dependencies.Should().HaveCount(1); + lib.Dependencies.Should().OnlyContain(l => l.Name == "System.Collections" && l.Version == "2.0.0"); + } [Fact] public void FillsCompileLibraryProperties() From 444e4f9fd71b7bebbc647eae7c0e9cd352645f30 Mon Sep 17 00:00:00 2001 From: Andrew Stanton-Nurse Date: Mon, 7 Mar 2016 09:34:18 -0800 Subject: [PATCH 06/31] update version of nuget --- .../NuGet.Config | 0 .../Packages/SharedContentA.1.0.0.nupkg | Bin .../project.json | 2 +- src/dotnet/commands/dotnet-restore/Program.cs | 6 ++++-- src/dotnet/project.json | 20 +++++++++--------- test/Installer/testmsi.ps1 | 8 +++---- 6 files changed, 18 insertions(+), 18 deletions(-) rename TestAssets/TestProjects/{TestAppWithContentPackage => }/NuGet.Config (100%) rename TestAssets/TestProjects/{TestAppWithContentPackage => }/Packages/SharedContentA.1.0.0.nupkg (100%) diff --git a/TestAssets/TestProjects/TestAppWithContentPackage/NuGet.Config b/TestAssets/TestProjects/NuGet.Config similarity index 100% rename from TestAssets/TestProjects/TestAppWithContentPackage/NuGet.Config rename to TestAssets/TestProjects/NuGet.Config diff --git a/TestAssets/TestProjects/TestAppWithContentPackage/Packages/SharedContentA.1.0.0.nupkg b/TestAssets/TestProjects/Packages/SharedContentA.1.0.0.nupkg similarity index 100% rename from TestAssets/TestProjects/TestAppWithContentPackage/Packages/SharedContentA.1.0.0.nupkg rename to TestAssets/TestProjects/Packages/SharedContentA.1.0.0.nupkg diff --git a/src/Microsoft.DotNet.ProjectModel/project.json b/src/Microsoft.DotNet.ProjectModel/project.json index 29752a4e7..82b9ecbe2 100644 --- a/src/Microsoft.DotNet.ProjectModel/project.json +++ b/src/Microsoft.DotNet.ProjectModel/project.json @@ -6,7 +6,7 @@ "description": "Types to model a .NET Project", "dependencies": { "System.Reflection.Metadata": "1.2.0-rc2-23901", - "NuGet.Packaging": "3.4.0-beta-632", + "NuGet.Packaging": "3.4.0-rtm-0724", "Microsoft.Extensions.FileSystemGlobbing": "1.0.0-rc2-15996", "Microsoft.Extensions.JsonParser.Sources": { "type": "build", diff --git a/src/dotnet/commands/dotnet-restore/Program.cs b/src/dotnet/commands/dotnet-restore/Program.cs index 8ca6057a1..a42330263 100644 --- a/src/dotnet/commands/dotnet-restore/Program.cs +++ b/src/dotnet/commands/dotnet-restore/Program.cs @@ -180,7 +180,7 @@ namespace Microsoft.DotNet.Tools.Restore Console.WriteLine($"Restoring Tool '{tooldep.Name}' for '{projectPath}' in '{tempPath}'"); File.WriteAllText(projectPath, GenerateProjectJsonContents(new[] {"netstandardapp1.5"}, tooldep)); - return NuGet3.Restore(new [] { $"{projectPath}", "--runtime", $"{DefaultRid}"}.Concat(args), quiet) == 0; + return NuGet3.Restore(new[] { $"{projectPath}" }.Concat(args), quiet) == 0; } private static string GenerateProjectJsonContents(IEnumerable frameworks, LibraryRange tooldep) @@ -194,9 +194,11 @@ namespace Microsoft.DotNet.Tools.Restore foreach (var framework in frameworks) { var importsStatement = "\"imports\": [ \"dnxcore50\", \"portable-net452+win81\" ]"; - sb.AppendLine($" \"{framework}\": {{ {importsStatement} }}"); } + sb.AppendLine(" },"); + sb.AppendLine(" \"runtimes\": { "); + sb.AppendLine($" \"{DefaultRid}\": {{}}"); sb.AppendLine(" }"); sb.AppendLine("}"); var pjContents = sb.ToString(); diff --git a/src/dotnet/project.json b/src/dotnet/project.json index b98fab4ff..dcc0b0182 100644 --- a/src/dotnet/project.json +++ b/src/dotnet/project.json @@ -3,16 +3,16 @@ "compilationOptions": { "emitEntryPoint": true }, - "compileExclude": [ - "commands/dotnet-new/CSharp_Console/**", - "commands/dotnet-new/FSharp_Console/**" + "compileExclude": [ + "commands/dotnet-new/CSharp_Console/**", + "commands/dotnet-new/FSharp_Console/**" ], - "resource": [ - "commands/dotnet-new/CSharp_Console/NuGet.Config", - "commands/dotnet-new/CSharp_Console/Program.cs", - "commands/dotnet-new/CSharp_Console/project.json.template", - "commands/dotnet-new/FSharp_Console/NuGet.config", - "commands/dotnet-new/FSharp_Console/Program.fs", + "resource": [ + "commands/dotnet-new/CSharp_Console/NuGet.Config", + "commands/dotnet-new/CSharp_Console/Program.cs", + "commands/dotnet-new/CSharp_Console/project.json.template", + "commands/dotnet-new/FSharp_Console/NuGet.config", + "commands/dotnet-new/FSharp_Console/Program.fs", "commands/dotnet-new/FSharp_Console/project.json.template" ], "dependencies": { @@ -24,7 +24,7 @@ "Microsoft.CodeAnalysis.CSharp": "1.3.0-beta1-20160225-02", "Microsoft.DiaSymReader.Native": "1.3.3", - "NuGet.CommandLine.XPlat": "3.4.0-beta-632", + "NuGet.CommandLine.XPlat": "3.4.0-rtm-0724", "System.CommandLine": "0.1.0-e160119-1", "Microsoft.DotNet.ProjectModel": "1.0.0-*", diff --git a/test/Installer/testmsi.ps1 b/test/Installer/testmsi.ps1 index 2a11669be..3f4f0d3cc 100644 --- a/test/Installer/testmsi.ps1 +++ b/test/Installer/testmsi.ps1 @@ -14,7 +14,7 @@ function CopyInstaller([string]$destination) # Copy both the .msi and the .exe to the testBin directory so # the tests running in the docker container have access to them. Copy-Item $inputMsi -Destination:$destination - + $BundlePath = [System.IO.Path]::ChangeExtension($inputMsi, "exe") Copy-Item $BundlePath -Destination:$destination } @@ -22,7 +22,7 @@ function CopyInstaller([string]$destination) function CopyTestXUnitRunner([string]$destination) { $XUnitRunnerDir = Join-Path $env:NUGET_PACKAGES xunit.runner.console\2.1.0\tools - + Copy-Item $XUnitRunnerDir\xunit.console.exe -Destination:$destination Copy-Item $XUnitRunnerDir\xunit.runner.utility.desktop.dll -Destination:$destination } @@ -42,7 +42,6 @@ pushd "$Stage2Dir\bin" try { .\dotnet restore ` - --runtime win-anycpu ` $testDir ` -f https://www.myget.org/F/dotnet-buildtools/api/v3/index.json | Out-Host @@ -53,7 +52,6 @@ try { .\dotnet publish ` --framework net46 ` - --runtime win-anycpu ` --output $testBin ` $testDir | Out-Host @@ -68,7 +66,7 @@ try { CopyTestXUnitRunner $testBin Write-Host "Running installer tests in Windows Container" - + # --net="none" works around a networking issue on the containers on the CI machines. # Since our installer tests don't require the network, it is fine to shut it off. $MsiFileName = [System.IO.Path]::GetFileName($inputMsi) From 7cc90d9ad1162db4a5bfcccd667f0f42a1132075 Mon Sep 17 00:00:00 2001 From: Andrew Stanton-Nurse Date: Tue, 1 Mar 2016 17:42:44 -0800 Subject: [PATCH 07/31] Update dotnet-build to produce portable layout dotnet-build will produce a deps file for portable builds, and will now create "runnable" outputs for RID-less targets the outputs won't actually be runnable today because we need corehost changes and to generate a deps.json file for corehost to use. --- .../BuildTestPortableProject/Lib.cs | 3 + .../BuildTestPortableProject/project.json | 16 +++++ .../BuildTestStandaloneProject/Lib.cs | 3 + .../BuildTestStandaloneProject/project.json | 20 ++++++ scripts/dev-dotnet.ps1 | 9 ++- scripts/dotnet-cli-build/CompileTargets.cs | 7 ++ src/Microsoft.DotNet.Cli.Utils/project.json | 5 +- .../Executable.cs | 12 ++-- .../OutputPathsCalculator.cs | 10 ++- src/Microsoft.DotNet.ProjectModel/Project.cs | 4 +- .../ProjectContext.cs | 26 +++---- .../ProjectReader.cs | 23 ++++--- .../commands/dotnet-build/CompileContext.cs | 29 ++++---- .../dotnet-compile/CompilerCommandApp.cs | 67 ++++++++++++------- .../dotnet-compile/ManagedCompiler.cs | 5 +- test/ArgumentForwardingTests/project.json | 2 +- .../Assertions/CommandResultAssertions.cs | 23 ++++++- .../Commands/BuildCommand.cs | 66 ++++++++++++------ .../BuildInvalidArgumentsTests.cs | 55 +++++++++++++++ test/dotnet-build.Tests/BuildPortableTests.cs | 44 ++++++++++++ .../BuildProjectToProjectTests.cs | 2 +- .../Microsoft.DotNet.Tools.Publish.Tests.cs | 2 +- 22 files changed, 334 insertions(+), 99 deletions(-) create mode 100644 TestAssets/TestProjects/BuildTestPortableProject/Lib.cs create mode 100644 TestAssets/TestProjects/BuildTestPortableProject/project.json create mode 100644 TestAssets/TestProjects/BuildTestStandaloneProject/Lib.cs create mode 100644 TestAssets/TestProjects/BuildTestStandaloneProject/project.json create mode 100644 test/dotnet-build.Tests/BuildInvalidArgumentsTests.cs create mode 100644 test/dotnet-build.Tests/BuildPortableTests.cs diff --git a/TestAssets/TestProjects/BuildTestPortableProject/Lib.cs b/TestAssets/TestProjects/BuildTestPortableProject/Lib.cs new file mode 100644 index 000000000..2ac94ca9d --- /dev/null +++ b/TestAssets/TestProjects/BuildTestPortableProject/Lib.cs @@ -0,0 +1,3 @@ +public static class Thingy +{ +} diff --git a/TestAssets/TestProjects/BuildTestPortableProject/project.json b/TestAssets/TestProjects/BuildTestPortableProject/project.json new file mode 100644 index 000000000..43c20c90b --- /dev/null +++ b/TestAssets/TestProjects/BuildTestPortableProject/project.json @@ -0,0 +1,16 @@ +{ + "dependencies": { + }, + "frameworks": { + "net45": {}, + "netstandardapp1.5": { + "imports": [ + "dnxcore50", + "portable-net45+win8" + ], + "dependencies": { + "NETStandard.Library": "1.0.0-rc2-23901" + } + } + } +} diff --git a/TestAssets/TestProjects/BuildTestStandaloneProject/Lib.cs b/TestAssets/TestProjects/BuildTestStandaloneProject/Lib.cs new file mode 100644 index 000000000..2ac94ca9d --- /dev/null +++ b/TestAssets/TestProjects/BuildTestStandaloneProject/Lib.cs @@ -0,0 +1,3 @@ +public static class Thingy +{ +} diff --git a/TestAssets/TestProjects/BuildTestStandaloneProject/project.json b/TestAssets/TestProjects/BuildTestStandaloneProject/project.json new file mode 100644 index 000000000..d8b5d9d86 --- /dev/null +++ b/TestAssets/TestProjects/BuildTestStandaloneProject/project.json @@ -0,0 +1,20 @@ +{ + "dependencies": { }, + "frameworks": { + "netstandardapp1.5": { + "imports": [ + "dnxcore50", + "portable-net45+win8" + ], + "dependencies": { + "NETStandard.Library": "1.0.0-rc2-23901" + } + } + }, + "runtimes": { + "win7-x64": {}, + "osx.10.10-x64": {}, + "ubuntu.14.04-x64": {}, + "centos.7-x64": {} + } +} diff --git a/scripts/dev-dotnet.ps1 b/scripts/dev-dotnet.ps1 index 8b5f1290f..4728a8b7c 100644 --- a/scripts/dev-dotnet.ps1 +++ b/scripts/dev-dotnet.ps1 @@ -6,11 +6,16 @@ $oldPath = $env:PATH try { # Put the stage2 output on the front of the path - $stage2 = "$PSScriptRoot\..\artifacts\win7-x64\stage2\bin" + if(!(Get-Command dotnet -ErrorAction SilentlyContinue)) { + throw "You need to have a version of 'dotnet' on your path so we can determine the RID" + } + + $rid = dotnet --version | where { $_ -match "^ Runtime Id:\s*(.*)$" } | foreach { $matches[1] } + $stage2 = "$PSScriptRoot\..\artifacts\$rid\stage2\bin" if (Test-Path $stage2) { $env:PATH="$stage2;$env:PATH" } else { - Write-Host "You don't have a dev build in the 'artifacts\win7-x64\stage2' folder!" + Write-Host "You don't have a dev build in the 'artifacts\$rid\stage2' folder!" } dotnet @args diff --git a/scripts/dotnet-cli-build/CompileTargets.cs b/scripts/dotnet-cli-build/CompileTargets.cs index b84fa6452..bbf03cf4f 100644 --- a/scripts/dotnet-cli-build/CompileTargets.cs +++ b/scripts/dotnet-cli-build/CompileTargets.cs @@ -45,6 +45,13 @@ namespace Microsoft.DotNet.Cli.Build "Microsoft.Extensions.Testing.Abstractions" }; + // Updates the stage 2 with recent changes. + [Target(nameof(PrepareTargets.Init), nameof(CompileStage2))] + public static BuildTargetResult UpdateBuild(BuildTargetContext c) + { + return c.Success(); + } + [Target(nameof(PrepareTargets.Init), nameof(CompileCoreHost), nameof(CompileStage1), nameof(CompileStage2))] public static BuildTargetResult Compile(BuildTargetContext c) { diff --git a/src/Microsoft.DotNet.Cli.Utils/project.json b/src/Microsoft.DotNet.Cli.Utils/project.json index 877df020f..625b48bf4 100644 --- a/src/Microsoft.DotNet.Cli.Utils/project.json +++ b/src/Microsoft.DotNet.Cli.Utils/project.json @@ -19,8 +19,9 @@ "netstandard1.3": { "imports": "dnxcore50", "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23901" + "NETStandard.Library": "1.0.0-rc2-23901", + "System.Diagnostics.Process": "4.1.0-rc2-23901" } } } -} \ No newline at end of file +} diff --git a/src/Microsoft.DotNet.Compiler.Common/Executable.cs b/src/Microsoft.DotNet.Compiler.Common/Executable.cs index 31f92825f..3aedeedc8 100644 --- a/src/Microsoft.DotNet.Compiler.Common/Executable.cs +++ b/src/Microsoft.DotNet.Compiler.Common/Executable.cs @@ -39,11 +39,6 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common public void MakeCompilationOutputRunnable() { - if (string.IsNullOrEmpty(_context.RuntimeIdentifier)) - { - throw new InvalidOperationException($"Can not make output runnable for framework {_context.TargetFramework}, because it doesn't have runtime target"); - } - CopyContentFiles(); ExportRuntimeAssets(); } @@ -72,8 +67,11 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common { WriteDepsFileAndCopyProjectDependencies(_exporter); - // TODO: Pick a host based on the RID - CoreHost.CopyTo(_runtimeOutputPath, _context.ProjectFile.Name + Constants.ExeSuffix); + if (!string.IsNullOrEmpty(_context.RuntimeIdentifier)) + { + // TODO: Pick a host based on the RID + CoreHost.CopyTo(_runtimeOutputPath, _context.ProjectFile.Name + Constants.ExeSuffix); + } } private void CopyContentFiles() diff --git a/src/Microsoft.DotNet.ProjectModel/OutputPathsCalculator.cs b/src/Microsoft.DotNet.ProjectModel/OutputPathsCalculator.cs index aa9c9fb87..fdaa7c5e3 100644 --- a/src/Microsoft.DotNet.ProjectModel/OutputPathsCalculator.cs +++ b/src/Microsoft.DotNet.ProjectModel/OutputPathsCalculator.cs @@ -48,12 +48,18 @@ namespace Microsoft.DotNet.ProjectModel { if (!string.IsNullOrEmpty(runtimeIdentifier)) { - runtimeOutputPath= PathUtility.EnsureTrailingSlash(Path.Combine(compilationOutputPath, runtimeIdentifier)); + runtimeOutputPath = PathUtility.EnsureTrailingSlash(Path.Combine(compilationOutputPath, runtimeIdentifier)); + } + else + { + // "Runtime" assets (i.e. the deps file) will be dropped to the compilation output path, because + // we are building a RID-less target. + runtimeOutputPath = compilationOutputPath; } } else { - runtimeOutputPath= PathUtility.EnsureTrailingSlash(Path.GetFullPath(outputPath)); + runtimeOutputPath = PathUtility.EnsureTrailingSlash(Path.GetFullPath(outputPath)); } var intermediateOutputPath = PathUtility.EnsureTrailingSlash(Path.Combine( diff --git a/src/Microsoft.DotNet.ProjectModel/Project.cs b/src/Microsoft.DotNet.ProjectModel/Project.cs index c4a8c4a41..5e187f55b 100644 --- a/src/Microsoft.DotNet.ProjectModel/Project.cs +++ b/src/Microsoft.DotNet.ProjectModel/Project.cs @@ -35,7 +35,7 @@ namespace Microsoft.DotNet.ProjectModel return Path.GetDirectoryName(ProjectFilePath); } } - + public AnalyzerOptions AnalyzerOptions { get; set; } public string Name { get; set; } @@ -124,12 +124,12 @@ namespace Microsoft.DotNet.ProjectModel public bool HasRuntimeOutput(string configuration) { - var compilationOptions = GetCompilerOptions(targetFramework: null, configurationName: configuration); // TODO: Make this opt in via another mechanism return compilationOptions.EmitEntryPoint.GetValueOrDefault() || IsTestProject; } + private CommonCompilerOptions GetCompilerOptions() { return _defaultCompilerOptions; diff --git a/src/Microsoft.DotNet.ProjectModel/ProjectContext.cs b/src/Microsoft.DotNet.ProjectModel/ProjectContext.cs index 9e237ff11..99f869f36 100644 --- a/src/Microsoft.DotNet.ProjectModel/ProjectContext.cs +++ b/src/Microsoft.DotNet.ProjectModel/ProjectContext.cs @@ -83,7 +83,7 @@ namespace Microsoft.DotNet.ProjectModel .WithRuntimeIdentifiers(runtimeIdentifiers) .Build(); } - + public static ProjectContextBuilder CreateBuilder(string projectPath, NuGetFramework framework) { if (projectPath.EndsWith(Project.FileName)) @@ -120,15 +120,12 @@ namespace Microsoft.DotNet.ProjectModel /// /// Creates a project context for each target located in the project at /// - public static IEnumerable CreateContextForEachTarget(string projectPath) + public static IEnumerable CreateContextForEachTarget(string projectPath, ProjectReaderSettings settings = null) { - if (!projectPath.EndsWith(Project.FileName)) - { - projectPath = Path.Combine(projectPath, Project.FileName); - } var project = ProjectReader.GetProject(projectPath); return new ProjectContextBuilder() + .WithReaderSettings(settings) .WithProject(project) .BuildAllTargets(); } @@ -143,15 +140,20 @@ namespace Microsoft.DotNet.ProjectModel public ProjectContext CreateRuntimeContext(IEnumerable runtimeIdentifiers) { - var context = Create(ProjectFile.ProjectFilePath, TargetFramework, runtimeIdentifiers); - if (context.RuntimeIdentifier == null) + // Check if there are any runtime targets (i.e. are we portable) + var standalone = LockFile.Targets + .Where(t => t.TargetFramework.Equals(TargetFramework)) + .Any(t => !string.IsNullOrEmpty(t.RuntimeIdentifier)); + + var context = Create(ProjectFile.ProjectFilePath, TargetFramework, standalone ? runtimeIdentifiers : Enumerable.Empty()); + if (standalone && context.RuntimeIdentifier == null) { + // We are standalone, but don't support this runtime var rids = string.Join(", ", runtimeIdentifiers); - throw new InvalidOperationException($"Can not find runtime target for framework '{TargetFramework}' and RID's '{rids}'. " + + throw new InvalidOperationException($"Can not find runtime target for framework '{TargetFramework}' compatible with one of the target runtimes: '{rids}'. " + "Possible causes:" + Environment.NewLine + - "1. Project is not restored or restore failed - run `dotnet restore`" + Environment.NewLine + - "2. Project is not targeting `runable` framework (`netstandardapp*` or `net*`)" - ); + "1. The project has not been restored or restore failed - run `dotnet restore`" + Environment.NewLine + + $"2. The project does not list one of '{rids}' in the 'runtimes' section."); } return context; } diff --git a/src/Microsoft.DotNet.ProjectModel/ProjectReader.cs b/src/Microsoft.DotNet.ProjectModel/ProjectReader.cs index 2a58b3bd5..39f28ba12 100644 --- a/src/Microsoft.DotNet.ProjectModel/ProjectReader.cs +++ b/src/Microsoft.DotNet.ProjectModel/ProjectReader.cs @@ -61,18 +61,20 @@ namespace Microsoft.DotNet.ProjectModel return true; } - public static Project GetProject(string projectFile, ProjectReaderSettings settings = null) - { - return GetProject(projectFile, new List(), settings); - } + public static Project GetProject(string projectPath, ProjectReaderSettings settings = null) => GetProject(projectPath, new List(), settings); - public static Project GetProject(string projectFile, ICollection diagnostics, ProjectReaderSettings settings = null) + public static Project GetProject(string projectPath, ICollection diagnostics, ProjectReaderSettings settings = null) { - var name = Path.GetFileName(Path.GetDirectoryName(projectFile)); - - using (var stream = new FileStream(projectFile, FileMode.Open, FileAccess.Read, FileShare.Read)) + if (!projectPath.EndsWith(Project.FileName)) { - return new ProjectReader().ReadProject(stream, name, projectFile, diagnostics, settings); + projectPath = Path.Combine(projectPath, Project.FileName); + } + + var name = Path.GetFileName(Path.GetDirectoryName(projectPath)); + + using (var stream = new FileStream(projectPath, FileMode.Open, FileAccess.Read, FileShare.Read)) + { + return new ProjectReader().ReadProject(stream, name, projectPath, diagnostics, settings); } } @@ -546,7 +548,8 @@ namespace Microsoft.DotNet.ProjectModel analyzerOptions.LanguageId = languageId; break; - default:; + default: + ; throw FileFormatException.Create( $"Unrecognized analyzerOption key: {key}", project.ProjectFilePath); diff --git a/src/dotnet/commands/dotnet-build/CompileContext.cs b/src/dotnet/commands/dotnet-build/CompileContext.cs index 7e0e43957..de2b43475 100644 --- a/src/dotnet/commands/dotnet-build/CompileContext.cs +++ b/src/dotnet/commands/dotnet-build/CompileContext.cs @@ -48,7 +48,7 @@ namespace Microsoft.DotNet.Tools.Build { CreateOutputDirectories(); - return CompileDendencies(incremental) && CompileRootProject(incremental); + return CompileDependencies(incremental) && CompileRootProject(incremental); } private bool CompileRootProject(bool incremental) @@ -66,7 +66,7 @@ namespace Microsoft.DotNet.Tools.Build return success; } - private bool CompileDendencies(bool incremental) + private bool CompileDependencies(bool incremental) { if (_args.ShouldSkipDependencies) { @@ -395,15 +395,7 @@ namespace Microsoft.DotNet.Tools.Build if (succeeded) { - if (_rootProject.ProjectFile.HasRuntimeOutput(_args.ConfigValue)) - { - MakeRunnable(); - } - else if (!string.IsNullOrEmpty(_args.OutputValue)) - { - var outputPaths = _rootProject.GetOutputPaths(_args.ConfigValue, _args.BuildBasePathValue, _args.OutputValue); - CopyCompilationOutput(outputPaths); - } + MakeRunnable(); } return succeeded; @@ -428,9 +420,22 @@ namespace Microsoft.DotNet.Tools.Build private void MakeRunnable() { var runtimeContext = _rootProject.CreateRuntimeContext(_args.GetRuntimes()); + if(_args.PortableMode) + { + // HACK: Force the use of the portable target + runtimeContext = _rootProject; + } + var outputPaths = runtimeContext.GetOutputPaths(_args.ConfigValue, _args.BuildBasePathValue, _args.OutputValue); var libraryExporter = runtimeContext.CreateExporter(_args.ConfigValue, _args.BuildBasePathValue); - CopyCompilationOutput(outputPaths); + + // If we're building for a specific RID, we need to copy the RID-less compilation output into + // the RID-specific output dir + if (!string.IsNullOrEmpty(runtimeContext.RuntimeIdentifier)) + { + CopyCompilationOutput(outputPaths); + } + var executable = new Executable(runtimeContext, outputPaths, libraryExporter); executable.MakeCompilationOutputRunnable(); diff --git a/src/dotnet/commands/dotnet-compile/CompilerCommandApp.cs b/src/dotnet/commands/dotnet-compile/CompilerCommandApp.cs index 2c7fa2a0f..9a66f1777 100644 --- a/src/dotnet/commands/dotnet-compile/CompilerCommandApp.cs +++ b/src/dotnet/commands/dotnet-compile/CompilerCommandApp.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using Microsoft.Dnx.Runtime.Common.CommandLine; @@ -28,6 +29,7 @@ namespace Microsoft.DotNet.Tools.Compiler private CommandOption _runtimeOption; private CommandOption _versionSuffixOption; private CommandOption _configurationOption; + private CommandOption _portableOption; private CommandArgument _projectArgument; private CommandOption _nativeOption; private CommandOption _archOption; @@ -41,8 +43,8 @@ namespace Microsoft.DotNet.Tools.Compiler // resolved values for the options and arguments public string ProjectPathValue { get; set; } public string BuildBasePathValue { get; set; } - public string OutputValue { get; set; } public string RuntimeValue { get; set; } + public string OutputValue { get; set; } public string VersionSuffixValue { get; set; } public string ConfigValue { get; set; } public bool IsNativeValue { get; set; } @@ -53,6 +55,7 @@ namespace Microsoft.DotNet.Tools.Compiler public bool IsCppModeValue { get; set; } public string AppDepSdkPathValue { get; set; } public string CppCompilerFlagsValue { get; set; } + public bool PortableMode { get; set; } // workaround: CommandLineApplication is internal therefore I cannot make _app protected so baseclasses can add their own params private readonly Dictionary baseClassOptions; @@ -77,12 +80,15 @@ namespace Microsoft.DotNet.Tools.Compiler _outputOption = _app.Option("-o|--output ", "Directory in which to place outputs", CommandOptionType.SingleValue); _buildBasePath = _app.Option("-b|--build-base-path ", "Directory in which to place temporary outputs", CommandOptionType.SingleValue); - _frameworkOption = _app.Option("-f|--framework ", "Compile a specific framework", CommandOptionType.MultipleValue); + _frameworkOption = _app.Option("-f|--framework ", "Compile a specific framework", CommandOptionType.SingleValue); + _runtimeOption = _app.Option("-r|--runtime ", "Produce runtime-specific assets for the specified runtime", CommandOptionType.SingleValue); _configurationOption = _app.Option("-c|--configuration ", "Configuration under which to build", CommandOptionType.SingleValue); - _runtimeOption = _app.Option("-r|--runtime ", "Target runtime to publish for", CommandOptionType.SingleValue); _versionSuffixOption = _app.Option("--version-suffix ", "Defines what `*` should be replaced with in version field in project.json", CommandOptionType.SingleValue); _projectArgument = _app.Argument("", "The project to compile, defaults to the current directory. Can be a path to a project.json or a project directory"); + // HACK: Allow us to treat a project as though it was portable by ignoring the runtime-specific targets. This is temporary until RID inference is removed from NuGet + _portableOption = _app.Option("--portable", "TEMPORARY: Enforces portable build/publish mode", CommandOptionType.NoValue); + // Native Args _nativeOption = _app.Option("-n|--native", "Compiles source to native machine code.", CommandOptionType.NoValue); _archOption = _app.Option("-a|--arch ", "The architecture for which to compile. x64 only currently supported.", CommandOptionType.SingleValue); @@ -98,6 +104,12 @@ namespace Microsoft.DotNet.Tools.Compiler { _app.OnExecute(() => { + if (_outputOption.HasValue() && !_frameworkOption.HasValue()) + { + Reporter.Error.WriteLine("When the '--output' option is provided, the '--framework' option must also be provided."); + return 1; + } + // Locate the project and get the name and full path ProjectPathValue = _projectArgument.Value; if (string.IsNullOrEmpty(ProjectPathValue)) @@ -110,6 +122,7 @@ namespace Microsoft.DotNet.Tools.Compiler ConfigValue = _configurationOption.Value() ?? Constants.DefaultConfiguration; RuntimeValue = _runtimeOption.Value(); VersionSuffixValue = _versionSuffixOption.Value(); + PortableMode = _portableOption.HasValue(); IsNativeValue = _nativeOption.HasValue(); ArchValue = _archOption.Value(); @@ -120,8 +133,6 @@ namespace Microsoft.DotNet.Tools.Compiler IsCppModeValue = _cppModeOption.HasValue(); CppCompilerFlagsValue = _cppCompilerFlagsOption.Value(); - IEnumerable contexts; - // Set defaults based on the environment var settings = ProjectReaderSettings.ReadFromEnvironment(); @@ -130,29 +141,35 @@ namespace Microsoft.DotNet.Tools.Compiler settings.VersionSuffix = VersionSuffixValue; } - if (_frameworkOption.HasValue()) + // Load the project file and construct all the targets + var targets = ProjectContext.CreateContextForEachFramework(ProjectPathValue, settings).ToList(); + + if (targets.Count == 0) { - contexts = _frameworkOption.Values - .Select(f => - { - return ProjectContext.CreateBuilder(ProjectPathValue, NuGetFramework.Parse(f)) - .WithReaderSettings(settings) - .Build(); - }); - } - else - { - if (!string.IsNullOrEmpty(OutputValue)) - { - throw new InvalidOperationException($"'{_frameworkOption.LongName}' is required when '{_outputOption.LongName}' is specified"); - } - else - { - contexts = ProjectContext.CreateContextForEachFramework(ProjectPathValue, settings); - } + // Project is missing 'frameworks' section + Reporter.Error.WriteLine("Project does not have any frameworks listed in the 'frameworks' section."); + return 1; } - var success = execute(contexts.ToList(), this); + // Filter the targets down based on the inputs + if (_frameworkOption.HasValue()) + { + var fx = NuGetFramework.Parse(_frameworkOption.Value()); + targets = targets.Where(t => fx.Equals(t.TargetFramework)).ToList(); + + if (targets.Count == 0) + { + // We filtered everything out + Reporter.Error.WriteLine($"Project does not support framework: {fx.DotNetFrameworkName}."); + return 1; + } + + Debug.Assert(targets.Count == 1); + } + + Debug.Assert(targets.All(t => string.IsNullOrEmpty(t.RuntimeIdentifier))); + + var success = execute(targets, this); return success ? 0 : 1; }); diff --git a/src/dotnet/commands/dotnet-compile/ManagedCompiler.cs b/src/dotnet/commands/dotnet-compile/ManagedCompiler.cs index aeb692979..d2b149b31 100644 --- a/src/dotnet/commands/dotnet-compile/ManagedCompiler.cs +++ b/src/dotnet/commands/dotnet-compile/ManagedCompiler.cs @@ -9,7 +9,6 @@ using Microsoft.DotNet.Cli.Compiler.Common; using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.ProjectModel; using Microsoft.DotNet.ProjectModel.Compilation; -using Microsoft.DotNet.ProjectModel.Utilities; using Microsoft.Extensions.DependencyModel; namespace Microsoft.DotNet.Tools.Compiler @@ -161,6 +160,10 @@ namespace Microsoft.DotNet.Tools.Compiler contextVariables.Add( "compile:RuntimeOutputDir", runtimeOutputPath.RuntimeOutputPath.TrimEnd('\\', '/')); + + contextVariables.Add( + "compile:RuntimeIdentifier", + runtimeContext.RuntimeIdentifier); } _scriptRunner.RunScripts(context, ScriptNames.PreCompile, contextVariables); diff --git a/test/ArgumentForwardingTests/project.json b/test/ArgumentForwardingTests/project.json index 7175750b5..8b99a663f 100644 --- a/test/ArgumentForwardingTests/project.json +++ b/test/ArgumentForwardingTests/project.json @@ -27,5 +27,5 @@ "testRunner": "xunit", - "scripts": { "precompile": "dotnet build ../ArgumentsReflector/project.json --framework netstandardapp1.5 --output %compile:RuntimeOutputDir%" } + "scripts": { "precompile": "dotnet build ../ArgumentsReflector/project.json --framework netstandardapp1.5 --runtime %compile:RuntimeIdentifier% --output %compile:RuntimeOutputDir%" } } diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/Assertions/CommandResultAssertions.cs b/test/Microsoft.DotNet.Tools.Tests.Utilities/Assertions/CommandResultAssertions.cs index 00516044b..3fab175b5 100644 --- a/test/Microsoft.DotNet.Tools.Tests.Utilities/Assertions/CommandResultAssertions.cs +++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/Assertions/CommandResultAssertions.cs @@ -60,7 +60,14 @@ namespace Microsoft.DotNet.Tools.Test.Utilities return new AndConstraint(this); } - public AndConstraint StdOutMatchPattern(string pattern, RegexOptions options = RegexOptions.None) + public AndConstraint HaveStdOutContaining(string pattern) + { + Execute.Assertion.ForCondition(_commandResult.StdOut.Contains(pattern)) + .FailWith(AppendDiagnosticsTo($"The command output did not contain expected result: {pattern}{Environment.NewLine}")); + return new AndConstraint(this); + } + + public AndConstraint HaveStdOutMatching(string pattern, RegexOptions options = RegexOptions.None) { Execute.Assertion.ForCondition(Regex.Match(_commandResult.StdOut, pattern, options).Success) .FailWith(AppendDiagnosticsTo($"Matching the command output failed. Pattern: {pattern}{Environment.NewLine}")); @@ -74,6 +81,20 @@ namespace Microsoft.DotNet.Tools.Test.Utilities return new AndConstraint(this); } + public AndConstraint HaveStdErrContaining(string pattern) + { + Execute.Assertion.ForCondition(_commandResult.StdErr.Contains(pattern)) + .FailWith(AppendDiagnosticsTo($"The command error output did not contain expected result: {pattern}{Environment.NewLine}")); + return new AndConstraint(this); + } + + public AndConstraint HaveStdErrMatching(string pattern, RegexOptions options = RegexOptions.None) + { + Execute.Assertion.ForCondition(Regex.Match(_commandResult.StdErr, pattern, options).Success) + .FailWith(AppendDiagnosticsTo($"Matching the command error output failed. Pattern: {pattern}{Environment.NewLine}")); + return new AndConstraint(this); + } + public AndConstraint NotHaveStdOut() { Execute.Assertion.ForCondition(string.IsNullOrEmpty(_commandResult.StdOut)) diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/BuildCommand.cs b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/BuildCommand.cs index 93102cf12..da059a1fe 100644 --- a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/BuildCommand.cs +++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/BuildCommand.cs @@ -11,23 +11,25 @@ namespace Microsoft.DotNet.Tools.Test.Utilities public sealed class BuildCommand : TestCommand { private Project _project; - private string _projectPath; - private string _outputDirectory; - private string _buidBasePathDirectory; - private string _configuration; - private string _framework; - private string _versionSuffix; - private bool _noHost; - private bool _native; - private string _architecture; - private string _ilcArgs; - private string _ilcPath; - private string _appDepSDKPath; - private bool _nativeCppMode; - private string _cppCompilerFlags; - private bool _buildProfile; - private bool _noIncremental; - private bool _noDependencies; + private readonly string _projectPath; + private readonly string _outputDirectory; + private readonly string _buidBasePathDirectory; + private readonly string _configuration; + private readonly string _framework; + private readonly string _versionSuffix; + private readonly bool _noHost; + private readonly bool _native; + private readonly string _architecture; + private readonly string _ilcArgs; + private readonly string _ilcPath; + private readonly string _appDepSDKPath; + private readonly bool _nativeCppMode; + private readonly string _cppCompilerFlags; + private readonly bool _buildProfile; + private readonly bool _noIncremental; + private readonly bool _noDependencies; + private readonly string _runtime; + private readonly bool _forcePortable; private string OutputOption { @@ -39,6 +41,16 @@ namespace Microsoft.DotNet.Tools.Test.Utilities } } + private string ForcePortableOption + { + get + { + return _forcePortable ? + "--portable" : + string.Empty; + } + } + private string BuildBasePathOption { get @@ -67,7 +79,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities $"--framework {_framework}"; } } - + private string VersionSuffixOption { get @@ -98,6 +110,16 @@ namespace Microsoft.DotNet.Tools.Test.Utilities } } + private string RuntimeOption + { + get + { + return _runtime == string.Empty ? + "" : + $"--runtime {_runtime}"; + } + } + private string ArchitectureOption { get @@ -194,6 +216,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities string buidBasePath="", string configuration="", string framework="", + string runtime="", string versionSuffix="", bool noHost=false, bool native=false, @@ -205,7 +228,8 @@ namespace Microsoft.DotNet.Tools.Test.Utilities string cppCompilerFlags="", bool buildProfile=true, bool noIncremental=false, - bool noDependencies=false + bool noDependencies=false, + bool forcePortable=false ) : base("dotnet") { @@ -217,6 +241,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities _configuration = configuration; _versionSuffix = versionSuffix; _framework = framework; + _runtime = runtime; _noHost = noHost; _native = native; _architecture = architecture; @@ -228,6 +253,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities _buildProfile = buildProfile; _noIncremental = noIncremental; _noDependencies = noDependencies; + _forcePortable = forcePortable; } public override CommandResult Execute(string args = "") @@ -251,7 +277,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities private string BuildArgs() { - return $"{BuildProfile} {NoDependencies} {NoIncremental} \"{_projectPath}\" {OutputOption} {BuildBasePathOption} {ConfigurationOption} {FrameworkOption} {VersionSuffixOption} {NoHostOption} {NativeOption} {ArchitectureOption} {IlcArgsOption} {IlcPathOption} {AppDepSDKPathOption} {NativeCppModeOption} {CppCompilerFlagsOption}"; + return $"{BuildProfile} {ForcePortableOption} {NoDependencies} {NoIncremental} \"{_projectPath}\" {OutputOption} {BuildBasePathOption} {ConfigurationOption} {FrameworkOption} {RuntimeOption} {VersionSuffixOption} {NoHostOption} {NativeOption} {ArchitectureOption} {IlcArgsOption} {IlcPathOption} {AppDepSDKPathOption} {NativeCppModeOption} {CppCompilerFlagsOption}"; } } } diff --git a/test/dotnet-build.Tests/BuildInvalidArgumentsTests.cs b/test/dotnet-build.Tests/BuildInvalidArgumentsTests.cs new file mode 100644 index 000000000..15a38b24b --- /dev/null +++ b/test/dotnet-build.Tests/BuildInvalidArgumentsTests.cs @@ -0,0 +1,55 @@ +using System.IO; +using Microsoft.DotNet.Tools.Test.Utilities; +using Xunit; + +namespace Microsoft.DotNet.Tools.Builder.Tests +{ + public class BuildInvalidArgumentsTests : TestBase + { + [Fact] + public void ErrorOccursWhenBuildingPortableProjectToSpecificOutputPathWithoutSpecifyingFramework() + { + var testInstance = TestAssetsManager.CreateTestInstance("BuildTestPortableProject") + .WithLockFiles(); + + var result = new BuildCommand( + projectPath: testInstance.TestRoot, + output: Path.Combine(testInstance.TestRoot, "out")) + .ExecuteWithCapturedOutput(); + + result.Should().Fail(); + result.Should().HaveStdErrContaining("When the '--output' option is provided, the '--framework' option must also be provided."); + } + + [Fact] + public void ErrorOccursWhenBuildingPortableProjectAndSpecifyingFrameworkThatProjectDoesNotSupport() + { + var testInstance = TestAssetsManager.CreateTestInstance("BuildTestPortableProject") + .WithLockFiles(); + + var result = new BuildCommand( + projectPath: testInstance.TestRoot, + output: Path.Combine(testInstance.TestRoot, "out"), + framework: "sl40") + .ExecuteWithCapturedOutput(); + + result.Should().Fail(); + result.Should().HaveStdErrContaining("Project does not support framework: Silverlight,Version=v4.0."); + } + + [Fact] + public void ErrorOccursWhenBuildingStandaloneProjectToSpecificOutputPathWithoutSpecifyingFramework() + { + var testInstance = TestAssetsManager.CreateTestInstance("BuildTestStandaloneProject") + .WithLockFiles(); + + var result = new BuildCommand( + projectPath: testInstance.TestRoot, + output: Path.Combine(testInstance.TestRoot, "out")) + .ExecuteWithCapturedOutput(); + + result.Should().Fail(); + result.Should().HaveStdErrContaining("When the '--output' option is provided, the '--framework' option must also be provided."); + } + } +} diff --git a/test/dotnet-build.Tests/BuildPortableTests.cs b/test/dotnet-build.Tests/BuildPortableTests.cs new file mode 100644 index 000000000..6ecfad1f1 --- /dev/null +++ b/test/dotnet-build.Tests/BuildPortableTests.cs @@ -0,0 +1,44 @@ +using System.IO; +using Microsoft.DotNet.Tools.Test.Utilities; +using Xunit; + +namespace Microsoft.DotNet.Tools.Builder.Tests +{ + public class BuildPortableTests : TestBase + { + [Fact] + public void BuildingAPortableProjectProducesDepsFile() + { + var testInstance = TestAssetsManager.CreateTestInstance("BuildTestPortableProject") + .WithLockFiles(); + + var result = new BuildCommand( + projectPath: testInstance.TestRoot, + forcePortable: true) + .ExecuteWithCapturedOutput(); + + result.Should().Pass(); + + var outputBase = new DirectoryInfo(Path.Combine(testInstance.TestRoot, "bin", "Debug")); + + var netstandardappOutput = outputBase.Sub("netstandardapp1.5"); + var fxSubdirs = new[] { + netstandardappOutput, + outputBase.Sub("net45") + }; + + foreach(var fxSubdir in fxSubdirs) + { + fxSubdir.Should() + .Exist().And + .HaveFiles(new[] + { + "BuildTestPortableProject.dll", + "BuildTestPortableProject.pdb" + }); + } + + netstandardappOutput.Should().HaveFile("BuildTestPortableProject.deps"); + } + } +} diff --git a/test/dotnet-build.Tests/BuildProjectToProjectTests.cs b/test/dotnet-build.Tests/BuildProjectToProjectTests.cs index c3b55a740..8735a84a6 100644 --- a/test/dotnet-build.Tests/BuildProjectToProjectTests.cs +++ b/test/dotnet-build.Tests/BuildProjectToProjectTests.cs @@ -75,7 +75,7 @@ namespace Microsoft.DotNet.Tools.Builder.Tests // second build with no dependencies and no incremental; only the root rebuilds var result2 = BuildProject(noDependencies: true, noIncremental: true); - result2.Should().StdOutMatchPattern("Compiling.*L0.*"); + result2.Should().HaveStdOutMatching("Compiling.*L0.*"); AssertResultDoesNotContainStrings(result2, dependencies); diff --git a/test/dotnet-publish.Tests/Microsoft.DotNet.Tools.Publish.Tests.cs b/test/dotnet-publish.Tests/Microsoft.DotNet.Tools.Publish.Tests.cs index c1dcfeda3..22562e818 100644 --- a/test/dotnet-publish.Tests/Microsoft.DotNet.Tools.Publish.Tests.cs +++ b/test/dotnet-publish.Tests/Microsoft.DotNet.Tools.Publish.Tests.cs @@ -188,7 +188,7 @@ namespace Microsoft.DotNet.Tools.Publish.Tests var publishCommand = new PublishCommand(testProject); var result = publishCommand.ExecuteWithCapturedOutput(); - result.Should().StdOutMatchPattern("\nprepublish_output( \\?[^%]+\\?){5}.+\npostpublish_output( \\?[^%]+\\?){5}", RegexOptions.Singleline); + result.Should().HaveStdOutMatching("\nprepublish_output( \\?[^%]+\\?){5}.+\npostpublish_output( \\?[^%]+\\?){5}", RegexOptions.Singleline); result.Should().Pass(); } } From dd3c0f50db98416b9912d94d7446a4d5310a1003 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Mon, 7 Mar 2016 10:51:40 -0800 Subject: [PATCH 08/31] Add reference assemblies and runtime targets support to dependency context builder. --- .../Compilation/LibraryExport.cs | 16 ++- .../Compilation/LibraryExportBuilder.cs | 47 ++++++- .../Compilation/LibraryExporter.cs | 24 ++++ .../Compilation/LibraryResourceAssembly.cs | 18 +++ .../Compilation/LibraryRuntimeTarget.cs | 32 +++++ .../DependencyContextBuilder.cs | 42 ++++-- .../Graph/LockFileReader.cs | 15 ++ .../Graph/LockFileRuntimeTarget.cs | 21 +++ .../Graph/LockFileTargetLibrary.cs | 2 + .../PackageDescription.cs | 4 +- .../CompilationLibrary.cs | 11 +- .../DependencyContextCsvReader.cs | 11 +- .../DependencyContextJsonReader.cs | 28 +++- .../DependencyContextStrings.cs | 4 + .../DependencyContextWriter.cs | 95 +++++++------ .../Library.cs | 5 +- .../ResourceAssembly.cs | 19 +++ .../RuntimeLibrary.cs | 14 +- .../RuntimeTarget.cs | 7 +- .../LibraryExporterPackageTests.cs | 130 ++++++++++++------ .../CompositeResolverTests.cs | 19 ++- .../DependencyContextBuilderTests.cs | 42 ++++-- .../DependencyContextJsonReaderTest.cs | 5 + .../DependencyContextJsonWriterTests.cs | 75 ++++++++++ 24 files changed, 556 insertions(+), 130 deletions(-) create mode 100644 src/Microsoft.DotNet.ProjectModel/Compilation/LibraryResourceAssembly.cs create mode 100644 src/Microsoft.DotNet.ProjectModel/Compilation/LibraryRuntimeTarget.cs create mode 100644 src/Microsoft.DotNet.ProjectModel/Graph/LockFileRuntimeTarget.cs create mode 100644 src/Microsoft.Extensions.DependencyModel/ResourceAssembly.cs diff --git a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExport.cs b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExport.cs index 0380fc56a..8d883495f 100644 --- a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExport.cs +++ b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExport.cs @@ -49,6 +49,16 @@ namespace Microsoft.DotNet.ProjectModel.Compilation /// public IEnumerable AnalyzerReferences { get; } + /// + /// Get a list of runtime targets provided by this export. + /// + public IEnumerable RuntimeTargets { get; } + + /// + /// Get a list of resource assemblies provided by this export. + /// + public IEnumerable ResourceAssemblies { get; } + public LibraryExport(LibraryDescription library, IEnumerable compileAssemblies, IEnumerable sourceReferences, @@ -56,7 +66,9 @@ namespace Microsoft.DotNet.ProjectModel.Compilation IEnumerable runtimeAssets, IEnumerable nativeLibraries, IEnumerable embeddedResources, - IEnumerable analyzers) + IEnumerable analyzers, + IEnumerable runtimeTargets, + IEnumerable resourceAssemblies) { Library = library; CompilationAssemblies = compileAssemblies; @@ -66,6 +78,8 @@ namespace Microsoft.DotNet.ProjectModel.Compilation NativeLibraries = nativeLibraries; EmbeddedResources = embeddedResources; AnalyzerReferences = analyzers; + RuntimeTargets = runtimeTargets; + ResourceAssemblies = resourceAssemblies; } private string DebuggerDisplay => Library.Identity.ToString(); diff --git a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExportBuilder.cs b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExportBuilder.cs index 42d98c897..3bf323893 100644 --- a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExportBuilder.cs +++ b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExportBuilder.cs @@ -26,6 +26,10 @@ namespace Microsoft.DotNet.ProjectModel.Compilation private IList _analyzerReferences; + private IList _runtimeTargets; + + private IList _resourceAssemblies; + public LibraryDescription Library { get; set; } public IEnumerable RuntimeAssemblies => _runtimeAssemblies; @@ -44,6 +48,10 @@ namespace Microsoft.DotNet.ProjectModel.Compilation public IEnumerable AnalyzerReferences => _analyzerReferences; + public IEnumerable RuntimeTargets => _runtimeTargets; + + public IEnumerable ResourceAssemblies => _resourceAssemblies; + public static LibraryExportBuilder Create(LibraryDescription library = null) { return new LibraryExportBuilder().WithLibrary(library); @@ -63,7 +71,9 @@ namespace Microsoft.DotNet.ProjectModel.Compilation RuntimeAssets ?? EmptyArray.Value, NativeLibraries ?? EmptyArray.Value, EmbeddedResources ?? EmptyArray.Value, - AnalyzerReferences ?? EmptyArray.Value); + AnalyzerReferences ?? EmptyArray.Value, + RuntimeTargets ?? EmptyArray.Value, + ResourceAssemblies ?? EmptyArray.Value); } public LibraryExportBuilder WithLibrary(LibraryDescription libraryDescription) @@ -89,7 +99,7 @@ namespace Microsoft.DotNet.ProjectModel.Compilation Replace(ref _compilationAssemblies, assets); return this; } - + public LibraryExportBuilder WithSourceReferences(IEnumerable assets) { Replace(ref _sourceReferences, assets); @@ -114,6 +124,18 @@ namespace Microsoft.DotNet.ProjectModel.Compilation return this; } + public LibraryExportBuilder WithRuntimeTargets(IEnumerable targets) + { + Replace(ref _runtimeTargets, targets); + return this; + } + + public LibraryExportBuilder WithResourceAssemblies(IEnumerable assemblies) + { + Replace(ref _resourceAssemblies, assemblies); + return this; + } + public LibraryExportBuilder AddRuntimeAssembly(LibraryAsset asset) { Add(ref _runtimeAssemblies, asset); @@ -156,9 +178,28 @@ namespace Microsoft.DotNet.ProjectModel.Compilation return this; } + public LibraryExportBuilder AddRuntimeTarget(LibraryRuntimeTarget target) + { + Add(ref _runtimeTargets, target); + return this; + } + + public LibraryExportBuilder AddResourceAssembly(LibraryResourceAssembly assembly) + { + Add(ref _resourceAssemblies, assembly); + return this; + } + private void Replace(ref IList list, IEnumerable enumerable) { - list = new List(enumerable); + if (enumerable == null) + { + list = null; + } + else + { + list = new List(enumerable); + } } private void Add(ref IList list, T item) diff --git a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs index 2679750f4..ba21b79e9 100644 --- a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs +++ b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs @@ -122,6 +122,8 @@ namespace Microsoft.DotNet.ProjectModel.Compilation .WithNativeLibraries(libraryExport.NativeLibraries) .WithEmbedddedResources(libraryExport.EmbeddedResources) .WithAnalyzerReference(analyzerReferences) + .WithResourceAssemblies(libraryExport.ResourceAssemblies) + .WithRuntimeTargets(libraryExport.RuntimeTargets) .Build(); } } @@ -199,6 +201,28 @@ namespace Microsoft.DotNet.ProjectModel.Compilation } } } + if (package.RuntimeTargets.Any()) + { + foreach (var targetGroup in package.RuntimeTargets.GroupBy(t => t.Runtime)) + { + var runtime = new List(); + var native = new List(); + + foreach (var lockFileRuntimeTarget in targetGroup) + { + if (string.Equals(lockFileRuntimeTarget.AssetType, "native", StringComparison.OrdinalIgnoreCase)) + { + native.Add(LibraryAsset.CreateFromRelativePath(package.Path, lockFileRuntimeTarget.Path)); + } + else if (string.Equals(lockFileRuntimeTarget.AssetType, "runtime", StringComparison.OrdinalIgnoreCase)) + { + runtime.Add(LibraryAsset.CreateFromRelativePath(package.Path, lockFileRuntimeTarget.Path)); + } + } + + builder.AddRuntimeTarget(new LibraryRuntimeTarget(targetGroup.Key, runtime, native)); + } + } return builder.Build(); } diff --git a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryResourceAssembly.cs b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryResourceAssembly.cs new file mode 100644 index 000000000..1520352c3 --- /dev/null +++ b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryResourceAssembly.cs @@ -0,0 +1,18 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace Microsoft.DotNet.ProjectModel.Compilation +{ + public class LibraryResourceAssembly + { + public LibraryResourceAssembly(LibraryAsset asset, string locale) + { + Asset = asset; + Locale = locale; + } + + public LibraryAsset Asset { get; } + + public string Locale { get; } + } +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryRuntimeTarget.cs b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryRuntimeTarget.cs new file mode 100644 index 000000000..9bf303411 --- /dev/null +++ b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryRuntimeTarget.cs @@ -0,0 +1,32 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Linq; +using System.Collections.Generic; + +namespace Microsoft.DotNet.ProjectModel.Compilation +{ + public class LibraryRuntimeTarget + { + public LibraryRuntimeTarget(string runtime, + IEnumerable runtimeAssemblies, + IEnumerable nativeLibraries) + { + Runtime = runtime; + RuntimeAssemblies = runtimeAssemblies.ToArray(); + NativeLibraries = nativeLibraries.ToArray(); + } + + public string Runtime { get; } + + /// + /// Gets a list of fully-qualified paths to MSIL binaries required to run + /// + public IReadOnlyList RuntimeAssemblies { get; } + + /// + /// Gets a list of fully-qualified paths to native binaries required to run + /// + public IReadOnlyList NativeLibraries { get; } + } +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs b/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs index da9ad8444..a44b0c410 100644 --- a/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs +++ b/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs @@ -49,8 +49,8 @@ namespace Microsoft.Extensions.DependencyModel runtime, false, GetCompilationOptions(compilerOptions), - GetLibraries(compilationExports, dependencyLookup, runtime: false).Cast().ToArray(), - GetLibraries(runtimeExports, dependencyLookup, runtime: true).Cast().ToArray(), + GetLibraries(compilationExports, dependencyLookup, runtime: false).Cast(), + GetLibraries(runtimeExports, dependencyLookup, runtime: true).Cast(), new KeyValuePair[0]); } @@ -107,14 +107,14 @@ namespace Microsoft.Extensions.DependencyModel } } - string[] assemblies; + IEnumerable assemblies; if (type == LibraryType.ReferenceAssembly) { assemblies = ResolveReferenceAssembliesPath(libraryAssets); } else { - assemblies = libraryAssets.Select(libraryAsset => libraryAsset.RelativePath).ToArray(); + assemblies = libraryAssets.Select(libraryAsset => libraryAsset.RelativePath); } if (runtime) @@ -124,9 +124,10 @@ namespace Microsoft.Extensions.DependencyModel export.Library.Identity.Name, export.Library.Identity.Version.ToString(), export.Library.Hash, - assemblies.Select(RuntimeAssembly.Create).ToArray(), - new RuntimeTarget[0], - libraryDependencies.ToArray(), + assemblies.Select(RuntimeAssembly.Create), + export.ResourceAssemblies.Select(CreateResourceAssembly), + export.RuntimeTargets.Select(CreateRuntimeTarget), + libraryDependencies, serviceable ); } @@ -138,15 +139,31 @@ namespace Microsoft.Extensions.DependencyModel export.Library.Identity.Version.ToString(), export.Library.Hash, assemblies, - libraryDependencies.ToArray(), + libraryDependencies, serviceable ); } } - private string[] ResolveReferenceAssembliesPath(IEnumerable libraryAssets) + private ResourceAssembly CreateResourceAssembly(LibraryResourceAssembly resourceAssembly) + { + return new ResourceAssembly( + path: resourceAssembly.Asset.RelativePath, + locale: resourceAssembly.Locale + ); + } + + private RuntimeTarget CreateRuntimeTarget(LibraryRuntimeTarget runtimeTarget) + { + return new RuntimeTarget( + runtime: runtimeTarget.Runtime, + assemblies: runtimeTarget.RuntimeAssemblies.Select(a => RuntimeAssembly.Create(a.RelativePath)), + nativeLibraries: runtimeTarget.NativeLibraries.Select(l => l.RelativePath) + ); + } + + private IEnumerable ResolveReferenceAssembliesPath(IEnumerable libraryAssets) { - var resolvedPaths = new List(); var referenceAssembliesPath = PathUtility.EnsureTrailingSlash(_referenceAssembliesPath); foreach (var libraryAsset in libraryAssets) @@ -155,14 +172,13 @@ namespace Microsoft.Extensions.DependencyModel // if not, save only assembly name and try to find it somehow later if (libraryAsset.ResolvedPath.StartsWith(referenceAssembliesPath)) { - resolvedPaths.Add(libraryAsset.ResolvedPath.Substring(referenceAssembliesPath.Length)); + yield return libraryAsset.ResolvedPath.Substring(referenceAssembliesPath.Length); } else { - resolvedPaths.Add(Path.GetFileName(libraryAsset.ResolvedPath)); + yield return Path.GetFileName(libraryAsset.ResolvedPath); } } - return resolvedPaths.ToArray(); } } } diff --git a/src/Microsoft.DotNet.ProjectModel/Graph/LockFileReader.cs b/src/Microsoft.DotNet.ProjectModel/Graph/LockFileReader.cs index 3985e20fd..dd5223aef 100644 --- a/src/Microsoft.DotNet.ProjectModel/Graph/LockFileReader.cs +++ b/src/Microsoft.DotNet.ProjectModel/Graph/LockFileReader.cs @@ -170,6 +170,21 @@ namespace Microsoft.DotNet.ProjectModel.Graph return library; } + private static LockFileRuntimeTarget ReadRuntimeTarget(string property, JsonValue json) + { + var jsonObject = json as JsonObject; + if (jsonObject == null) + { + throw FileFormatException.Create("The value type is not an object.", json); + } + + return new LockFileRuntimeTarget( + path: property, + runtime: jsonObject.ValueAsString("runtime"), + assetType: jsonObject.ValueAsString("assetType") + ); + } + private static LockFileContentFile ReadContentFile(string property, JsonValue json) { var contentFile = new LockFileContentFile() diff --git a/src/Microsoft.DotNet.ProjectModel/Graph/LockFileRuntimeTarget.cs b/src/Microsoft.DotNet.ProjectModel/Graph/LockFileRuntimeTarget.cs new file mode 100644 index 000000000..2573c1680 --- /dev/null +++ b/src/Microsoft.DotNet.ProjectModel/Graph/LockFileRuntimeTarget.cs @@ -0,0 +1,21 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace Microsoft.DotNet.ProjectModel.Graph +{ + public class LockFileRuntimeTarget + { + public LockFileRuntimeTarget(string path, string runtime, string assetType) + { + Path = path; + Runtime = runtime; + AssetType = assetType; + } + + public string Path { get; } + + public string Runtime { get; } + + public string AssetType { get; } + } +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.ProjectModel/Graph/LockFileTargetLibrary.cs b/src/Microsoft.DotNet.ProjectModel/Graph/LockFileTargetLibrary.cs index eb593e3a4..f35cdb031 100644 --- a/src/Microsoft.DotNet.ProjectModel/Graph/LockFileTargetLibrary.cs +++ b/src/Microsoft.DotNet.ProjectModel/Graph/LockFileTargetLibrary.cs @@ -32,5 +32,7 @@ namespace Microsoft.DotNet.ProjectModel.Graph public IList NativeLibraries { get; set; } = new List(); public IList ContentFiles { get; set; } = new List(); + + public IList RuntimeTargets { get; set; } = new List(); } } diff --git a/src/Microsoft.DotNet.ProjectModel/PackageDescription.cs b/src/Microsoft.DotNet.ProjectModel/PackageDescription.cs index fc75e998e..ab050b72b 100644 --- a/src/Microsoft.DotNet.ProjectModel/PackageDescription.cs +++ b/src/Microsoft.DotNet.ProjectModel/PackageDescription.cs @@ -32,7 +32,7 @@ namespace Microsoft.DotNet.ProjectModel } private LockFileTargetLibrary Target { get; } - + public LockFilePackageLibrary Library { get; } public IEnumerable RuntimeAssemblies => FilterPlaceholders(Target.RuntimeAssemblies); @@ -45,6 +45,8 @@ namespace Microsoft.DotNet.ProjectModel public IEnumerable ContentFiles => Target.ContentFiles; + public IEnumerable RuntimeTargets => Target.RuntimeTargets; + private IEnumerable FilterPlaceholders(IList items) { return items.Where(a => !PackageDependencyProvider.IsPlaceholderFile(a)); diff --git a/src/Microsoft.Extensions.DependencyModel/CompilationLibrary.cs b/src/Microsoft.Extensions.DependencyModel/CompilationLibrary.cs index 1d5490f0f..2a85c2f8e 100644 --- a/src/Microsoft.Extensions.DependencyModel/CompilationLibrary.cs +++ b/src/Microsoft.Extensions.DependencyModel/CompilationLibrary.cs @@ -3,16 +3,23 @@ using System; using System.Collections.Generic; +using System.Linq; using Microsoft.Extensions.DependencyModel.Resolution; namespace Microsoft.Extensions.DependencyModel { public class CompilationLibrary : Library { - public CompilationLibrary(string type, string name, string version, string hash, string[] assemblies, Dependency[] dependencies, bool serviceable) + public CompilationLibrary(string type, + string name, + string version, + string hash, + IEnumerable assemblies, + IEnumerable dependencies, + bool serviceable) : base(type, name, version, hash, dependencies, serviceable) { - Assemblies = assemblies; + Assemblies = assemblies.ToArray(); } public IReadOnlyList Assemblies { get; } diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextCsvReader.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextCsvReader.cs index 8008fe065..69c4b2bf2 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextCsvReader.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextCsvReader.cs @@ -46,9 +46,10 @@ namespace Microsoft.Extensions.DependencyModel name: identity.Item2, version: identity.Item3, hash: identity.Item4, - assemblies: packageGroup.Select(l => RuntimeAssembly.Create(l.AssetPath)).ToArray(), - subTargets: new RuntimeTarget[0], - dependencies: new Dependency[] { }, + assemblies: packageGroup.Select(l => RuntimeAssembly.Create(l.AssetPath)), + resourceAssemblies: Enumerable.Empty(), + subTargets: Enumerable.Empty(), + dependencies: Enumerable.Empty(), serviceable: false )); } @@ -58,9 +59,9 @@ namespace Microsoft.Extensions.DependencyModel runtime: string.Empty, isPortable: false, compilationOptions: CompilationOptions.Default, - compileLibraries: new CompilationLibrary[] {}, + compileLibraries: Enumerable.Empty(), runtimeLibraries: runtimeLibraries.ToArray(), - runtimeGraph: new KeyValuePair[0]); + runtimeGraph: Enumerable.Empty>()); } private Tuple PackageIdentity(DepsFileLine line) diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs index e16498313..3dc15822f 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs @@ -173,7 +173,18 @@ namespace Microsoft.Extensions.DependencyModel .Select(RuntimeAssembly.Create) .ToArray(); - return new RuntimeLibrary(stub.Type, name, version, stub.Hash, assemblies, runtimeTargets.ToArray(), dependencies, stub.Serviceable); + var resourceAssemblies = ReadResourceAssemblies((JObject)libraryObject[DependencyContextStrings.ResourceAssembliesPropertyName]); + + return new RuntimeLibrary( + type: stub.Type, + name: name, + version: version, + hash: stub.Hash, + assemblies: assemblies, + resourceAssemblies: resourceAssemblies, + subTargets: runtimeTargets.ToArray(), + dependencies: dependencies, + serviceable: stub.Serviceable); } else { @@ -182,6 +193,21 @@ namespace Microsoft.Extensions.DependencyModel } } + private IEnumerable ReadResourceAssemblies(JObject resourcesObject) + { + if (resourcesObject == null) + { + yield break; + } + foreach (var resourceProperty in resourcesObject) + { + yield return new ResourceAssembly( + locale: resourceProperty.Value[DependencyContextStrings.LocalePropertyName]?.Value(), + path: resourceProperty.Key + ); + } + } + private static IEnumerable ReadRuntimeTargetEntries(JObject runtimeTargetObject) { if (runtimeTargetObject == null) diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextStrings.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextStrings.cs index e42a850b5..7f098877e 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextStrings.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextStrings.cs @@ -66,5 +66,9 @@ namespace Microsoft.Extensions.DependencyModel internal const string RuntimeAssetType = "runtime"; internal const string NativeAssetType = "native"; + + internal const string ResourceAssembliesPropertyName = "resources"; + + internal const string LocalePropertyName = "locale"; } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs index a63f622d4..c5e0ca8ee 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs @@ -140,49 +140,70 @@ namespace Microsoft.Extensions.DependencyModel return targetObject; } + private void AddCompilationAssemblies(JObject libraryObject, IEnumerable compilationAssemblies) + { + libraryObject.Add(new JProperty(DependencyContextStrings.CompileTimeAssembliesKey, + WriteAssemblies(compilationAssemblies)) + ); + } + + private void AddRuntimeAssemblies(JObject libraryObject, IEnumerable runtimeAssemblies) + { + libraryObject.Add(new JProperty(DependencyContextStrings.RuntimeAssembliesKey, + WriteAssemblies(runtimeAssemblies.Select(a => a.Path))) + ); + } + + private void AddDependencies(JObject libraryObject, IEnumerable dependencies) + { + libraryObject.Add( + new JProperty(DependencyContextStrings.DependenciesPropertyName, + new JObject( + dependencies.Select(dependency => new JProperty(dependency.Name, dependency.Version)))) + ); + } + + private void AddResourceAssemblies(JObject libraryObject, IEnumerable resourceAssemblies) + { + libraryObject.Add(DependencyContextStrings.ResourceAssembliesPropertyName, + new JObject(resourceAssemblies.Select(a => + new JProperty(a.Path, new JObject(new JProperty(DependencyContextStrings.LocalePropertyName, a.Locale)))) + ) + ); + } + private JObject WriteTargetLibrary(Library library) { - string propertyName; - string[] assemblies; - var runtimeLibrary = library as RuntimeLibrary; if (runtimeLibrary != null) { - propertyName = DependencyContextStrings.RuntimeAssembliesKey; - assemblies = runtimeLibrary.Assemblies.Select(assembly => assembly.Path).ToArray(); + var libraryObject = new JObject(); + AddDependencies(libraryObject, runtimeLibrary.Dependencies); + AddRuntimeAssemblies(libraryObject, runtimeLibrary.Assemblies); + AddResourceAssemblies(libraryObject, runtimeLibrary.ResourceAssemblies); + return libraryObject; } - else + + var compilationLibrary = library as CompilationLibrary; + if (compilationLibrary != null) { - var compilationLibrary = library as CompilationLibrary; - if (compilationLibrary != null) - { - propertyName = DependencyContextStrings.CompileTimeAssembliesKey; - assemblies = compilationLibrary.Assemblies.ToArray(); - } - else - { - throw new NotSupportedException(); - } + var libraryObject = new JObject(); + AddDependencies(libraryObject, compilationLibrary.Dependencies); + AddCompilationAssemblies(libraryObject, compilationLibrary.Assemblies); + return libraryObject; } - - - return new JObject( - new JProperty(DependencyContextStrings.DependenciesPropertyName, WriteDependencies(library.Dependencies)), - new JProperty(propertyName, - WriteAssemblies(assemblies)) - ); + throw new NotSupportedException(); } private JObject WritePortableTargetLibrary(RuntimeLibrary runtimeLibrary, CompilationLibrary compilationLibrary) { - var libraryObject = new JObject(); - var dependencies = new HashSet(); + var libraryObject = new JObject(); + + var dependencies = new HashSet(); if (runtimeLibrary != null) { - libraryObject.Add(new JProperty(DependencyContextStrings.RuntimeAssembliesKey, - WriteAssemblies(runtimeLibrary.Assemblies.Select(a => a.Path))) - ); + if (runtimeLibrary.RuntimeTargets.Any()) { libraryObject.Add(new JProperty( @@ -190,21 +211,20 @@ namespace Microsoft.Extensions.DependencyModel new JObject(runtimeLibrary.RuntimeTargets.SelectMany(WriteRuntimeTarget))) ); } + AddResourceAssemblies(libraryObject, runtimeLibrary.ResourceAssemblies); + AddRuntimeAssemblies(libraryObject, runtimeLibrary.Assemblies); dependencies.UnionWith(runtimeLibrary.Dependencies); } if (compilationLibrary != null) { - libraryObject.Add(new JProperty(DependencyContextStrings.CompileTimeAssembliesKey, - WriteAssemblies(compilationLibrary.Assemblies)) - ); + AddCompilationAssemblies(libraryObject, compilationLibrary.Assemblies); + dependencies.UnionWith(compilationLibrary.Dependencies); } - libraryObject.Add( - new JProperty(DependencyContextStrings.DependenciesPropertyName, WriteDependencies(dependencies))); - + AddDependencies(libraryObject, dependencies); return libraryObject; } @@ -241,13 +261,6 @@ namespace Microsoft.Extensions.DependencyModel return new JObject(assemblies.Select(assembly => new JProperty(assembly, new JObject()))); } - private JObject WriteDependencies(IEnumerable dependencies) - { - return new JObject( - dependencies.Select(dependency => new JProperty(dependency.Name, dependency.Version)) - ); - } - private JObject WriteLibraries(DependencyContext context) { var allLibraries = diff --git a/src/Microsoft.Extensions.DependencyModel/Library.cs b/src/Microsoft.Extensions.DependencyModel/Library.cs index 74c5cc2ef..a3fefef42 100644 --- a/src/Microsoft.Extensions.DependencyModel/Library.cs +++ b/src/Microsoft.Extensions.DependencyModel/Library.cs @@ -1,19 +1,20 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System.Linq; using System.Collections.Generic; namespace Microsoft.Extensions.DependencyModel { public class Library { - public Library(string type, string name, string version, string hash, Dependency[] dependencies, bool serviceable) + public Library(string type, string name, string version, string hash, IEnumerable dependencies, bool serviceable) { Type = type; Name = name; Version = version; Hash = hash; - Dependencies = dependencies; + Dependencies = dependencies.ToArray(); Serviceable = serviceable; } diff --git a/src/Microsoft.Extensions.DependencyModel/ResourceAssembly.cs b/src/Microsoft.Extensions.DependencyModel/ResourceAssembly.cs new file mode 100644 index 000000000..416ed20b1 --- /dev/null +++ b/src/Microsoft.Extensions.DependencyModel/ResourceAssembly.cs @@ -0,0 +1,19 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace Microsoft.Extensions.DependencyModel +{ + public class ResourceAssembly + { + public ResourceAssembly(string path, string locale) + { + Locale = locale; + Path = path; + } + + public string Locale { get; set; } + + public string Path { get; set; } + + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.DependencyModel/RuntimeLibrary.cs b/src/Microsoft.Extensions.DependencyModel/RuntimeLibrary.cs index 4519e8590..a3ee2332f 100644 --- a/src/Microsoft.Extensions.DependencyModel/RuntimeLibrary.cs +++ b/src/Microsoft.Extensions.DependencyModel/RuntimeLibrary.cs @@ -13,18 +13,22 @@ namespace Microsoft.Extensions.DependencyModel string name, string version, string hash, - RuntimeAssembly[] assemblies, - RuntimeTarget[] subTargets, - Dependency[] dependencies, + IEnumerable assemblies, + IEnumerable resourceAssemblies, + IEnumerable subTargets, + IEnumerable dependencies, bool serviceable) : base(type, name, version, hash, dependencies, serviceable) { - Assemblies = assemblies; - RuntimeTargets = subTargets; + Assemblies = assemblies.ToArray(); + ResourceAssemblies = resourceAssemblies.ToArray(); + RuntimeTargets = subTargets.ToArray(); } public IReadOnlyList Assemblies { get; } + public IReadOnlyList ResourceAssemblies { get; } + public IReadOnlyList RuntimeTargets { get; } } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.DependencyModel/RuntimeTarget.cs b/src/Microsoft.Extensions.DependencyModel/RuntimeTarget.cs index 15b5d9d7f..81771662b 100644 --- a/src/Microsoft.Extensions.DependencyModel/RuntimeTarget.cs +++ b/src/Microsoft.Extensions.DependencyModel/RuntimeTarget.cs @@ -1,14 +1,15 @@ using System.Collections.Generic; +using System.Linq; namespace Microsoft.Extensions.DependencyModel { public class RuntimeTarget { - public RuntimeTarget(string runtime, IReadOnlyList assemblies, IReadOnlyList nativeLibraries) + public RuntimeTarget(string runtime, IEnumerable assemblies, IEnumerable nativeLibraries) { Runtime = runtime; - Assemblies = assemblies; - NativeLibraries = nativeLibraries; + Assemblies = assemblies.ToArray(); + NativeLibraries = nativeLibraries.ToArray(); } public string Runtime { get; } diff --git a/test/Microsoft.DotNet.ProjectModel.Tests/LibraryExporterPackageTests.cs b/test/Microsoft.DotNet.ProjectModel.Tests/LibraryExporterPackageTests.cs index 2b845545d..b056deedc 100644 --- a/test/Microsoft.DotNet.ProjectModel.Tests/LibraryExporterPackageTests.cs +++ b/test/Microsoft.DotNet.ProjectModel.Tests/LibraryExporterPackageTests.cs @@ -1,3 +1,6 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System; using System.Collections.Generic; using System.IO; @@ -15,36 +18,6 @@ namespace Microsoft.DotNet.ProjectModel.Tests { private const string PackagePath = "PackagePath"; - private LibraryExport ExportSingle(LibraryDescription description = null) - { - var rootProject = new Project() - { - Name = "RootProject", - CompilerName = "csc" - }; - - var rootProjectDescription = new ProjectDescription( - new LibraryRange(), - rootProject, - new LibraryRange[] { }, - new TargetFrameworkInformation(), - true); - - if (description == null) - { - description = rootProjectDescription; - } - else - { - description.Parents.Add(rootProjectDescription); - } - - var libraryManager = new LibraryManager(new[] { description }, new DiagnosticMessage[] { }, ""); - var allExports = new LibraryExporter(rootProjectDescription, libraryManager, "config", "runtime", "basepath", "solutionroot").GetAllExports(); - var export = allExports.Single(); - return export; - } - private PackageDescription CreateDescription(LockFileTargetLibrary target = null, LockFilePackageLibrary package = null) { return new PackageDescription(PackagePath, @@ -54,7 +27,7 @@ namespace Microsoft.DotNet.ProjectModel.Tests } [Fact] - private void ExportsPackageNativeLibraries() + public void ExportsPackageNativeLibraries() { var description = CreateDescription( new LockFileTargetLibrary() @@ -76,7 +49,7 @@ namespace Microsoft.DotNet.ProjectModel.Tests } [Fact] - private void ExportsPackageCompilationAssebmlies() + public void ExportsPackageCompilationAssebmlies() { var description = CreateDescription( new LockFileTargetLibrary() @@ -98,7 +71,7 @@ namespace Microsoft.DotNet.ProjectModel.Tests } [Fact] - private void ExportsPackageRuntimeAssebmlies() + public void ExportsPackageRuntimeAssebmlies() { var description = CreateDescription( new LockFileTargetLibrary() @@ -120,7 +93,7 @@ namespace Microsoft.DotNet.ProjectModel.Tests } [Fact] - private void ExportsSources() + public void ExportsSources() { var description = CreateDescription( package: new LockFilePackageLibrary() @@ -142,7 +115,7 @@ namespace Microsoft.DotNet.ProjectModel.Tests } [Fact] - private void ExportsCopyToOutputContentFiles() + public void ExportsCopyToOutputContentFiles() { var description = CreateDescription( new LockFileTargetLibrary() @@ -170,7 +143,7 @@ namespace Microsoft.DotNet.ProjectModel.Tests [Fact] - private void ExportsResourceContentFiles() + public void ExportsResourceContentFiles() { var description = CreateDescription( new LockFileTargetLibrary() @@ -196,7 +169,7 @@ namespace Microsoft.DotNet.ProjectModel.Tests } [Fact] - private void ExportsCompileContentFiles() + public void ExportsCompileContentFiles() { var description = CreateDescription( new LockFileTargetLibrary() @@ -224,7 +197,7 @@ namespace Microsoft.DotNet.ProjectModel.Tests [Fact] - private void SelectsContentFilesOfProjectCodeLanguage() + public void SelectsContentFilesOfProjectCodeLanguage() { var description = CreateDescription( new LockFileTargetLibrary() @@ -264,7 +237,7 @@ namespace Microsoft.DotNet.ProjectModel.Tests } [Fact] - private void SelectsContentFilesWithNoLanguageIfProjectLanguageNotMathed() + public void SelectsContentFilesWithNoLanguageIfProjectLanguageNotMathed() { var description = CreateDescription( new LockFileTargetLibrary() @@ -295,5 +268,84 @@ namespace Microsoft.DotNet.ProjectModel.Tests libraryAsset.RelativePath.Should().Be(Path.Combine("content", "file.any")); libraryAsset.ResolvedPath.Should().Be(Path.Combine(PackagePath, "content", "file.any")); } + + [Fact] + public void ExportsRuntimeTargets() + { + var win8Native = Path.Combine("native", "win8-x64", "Native.dll"); + var win8Runtime = Path.Combine("runtime", "win8-x64", "Runtime.dll"); + var linuxNative = Path.Combine("native", "linux", "Native.dll"); + + var description = CreateDescription( + new LockFileTargetLibrary() + { + RuntimeTargets = new List() + { + new LockFileRuntimeTarget( + path: win8Native, + runtime: "win8-x64", + assetType: "native" + ), + new LockFileRuntimeTarget( + path: win8Runtime, + runtime: "win8-x64", + assetType: "runtime" + ), + new LockFileRuntimeTarget( + path: linuxNative, + runtime: "linux", + assetType: "native" + ), + } + }); + + var result = ExportSingle(description); + result.RuntimeTargets.Should().HaveCount(2); + + var runtimeTarget = result.RuntimeTargets.Should().Contain(t => t.Runtime == "win8-x64").Subject; + var runtime = runtimeTarget.RuntimeAssemblies.Single(); + runtime.RelativePath.Should().Be(win8Runtime); + runtime.ResolvedPath.Should().Be(Path.Combine(PackagePath, win8Runtime)); + + var native = runtimeTarget.NativeLibraries.Single(); + native.RelativePath.Should().Be(win8Native); + native.ResolvedPath.Should().Be(Path.Combine(PackagePath, win8Native)); + + runtimeTarget = result.RuntimeTargets.Should().Contain(t => t.Runtime == "linux").Subject; + native = runtimeTarget.NativeLibraries.Single(); + native.RelativePath.Should().Be(linuxNative); + native.ResolvedPath.Should().Be(Path.Combine(PackagePath, linuxNative)); + } + + private LibraryExport ExportSingle(LibraryDescription description = null) + { + var rootProject = new Project() + { + Name = "RootProject", + CompilerName = "csc" + }; + + var rootProjectDescription = new ProjectDescription( + new LibraryRange(), + rootProject, + new LibraryRange[] { }, + new TargetFrameworkInformation(), + true); + + if (description == null) + { + description = rootProjectDescription; + } + else + { + description.Parents.Add(rootProjectDescription); + } + + var libraryManager = new LibraryManager(new[] { description }, new DiagnosticMessage[] { }, ""); + var allExports = new LibraryExporter(rootProjectDescription, libraryManager, "config", "runtime", "basepath", "solutionroot").GetAllExports(); + var export = allExports.Single(); + return export; + } + } } diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/CompositeResolverTests.cs b/test/Microsoft.Extensions.DependencyModel.Tests/CompositeResolverTests.cs index f1894aceb..c78bf7d4a 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/CompositeResolverTests.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/CompositeResolverTests.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using Microsoft.Extensions.DependencyModel; using Microsoft.Extensions.DependencyModel.Resolution; using Moq; @@ -54,7 +55,14 @@ namespace StreamForwarderTests failTwo.Object }; - var library = new CompilationLibrary(string.Empty, string.Empty, string.Empty, string.Empty, null, null, false); + var library = new CompilationLibrary( + string.Empty, + string.Empty, + string.Empty, + string.Empty, + Enumerable.Empty(), + Enumerable.Empty(), + false); var resolver = new CompositeCompilationAssemblyResolver(resolvers); var result = resolver.TryResolveAssemblyPaths(library, null); @@ -82,7 +90,14 @@ namespace StreamForwarderTests }; var assemblies = new List(); - var library = new CompilationLibrary(string.Empty, string.Empty, string.Empty, string.Empty, null, null, false); + var library = new CompilationLibrary( + string.Empty, + string.Empty, + string.Empty, + string.Empty, + Enumerable.Empty(), + Enumerable.Empty(), + false); var resolver = new CompositeCompilationAssemblyResolver(resolvers); var result = resolver.TryResolveAssemblyPaths(library, assemblies); diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs index 13eaefaa0..a92199f82 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs @@ -104,9 +104,24 @@ namespace Microsoft.Extensions.DependencyModel.Tests LibraryType.ReferenceAssembly, LibraryDependencyType.Default) }), + resourceAssemblies: new[] + { + new LibraryResourceAssembly( + new LibraryAsset("Dll", "en-US/Pack.Age.resources.dll", ""), + "en-US" + ) + }, runtimeAssemblies: new[] { new LibraryAsset("Dll", "lib/Pack.Age.dll", ""), + }, + runtimeTargets: new [] + { + new LibraryRuntimeTarget( + "win8-x64", + new [] { new LibraryAsset("Dll", "win8-x64/Pack.Age.dll", "") }, + new [] { new LibraryAsset("Dll", "win8-x64/Pack.Age.native.dll", "") } + ) } ), Export(ReferenceAssemblyDescription("System.Collections", @@ -126,6 +141,11 @@ namespace Microsoft.Extensions.DependencyModel.Tests lib.Version.Should().Be("1.2.3"); lib.Dependencies.Should().OnlyContain(l => l.Name == "System.Collections" && l.Version == "3.3.3"); lib.Assemblies.Should().OnlyContain(l => l.Path == "lib/Pack.Age.dll"); + lib.ResourceAssemblies.Should().OnlyContain(l => l.Path == "en-US/Pack.Age.resources.dll" && l.Locale == "en-US"); + + var target = lib.RuntimeTargets.Should().Contain(t => t.Runtime == "win8-x64").Subject; + target.Assemblies.Should().OnlyContain(l => l.Path == "win8-x64/Pack.Age.dll"); + target.NativeLibraries.Should().OnlyContain(l => l == "win8-x64/Pack.Age.native.dll"); var asm = context.RuntimeLibraries.Should().Contain(l => l.Name == "System.Collections").Subject; asm.Type.Should().Be("referenceassembly"); @@ -204,7 +224,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests public void SkipsBuildDependencies() { var context = Build(compilationExports: new[] - { + { Export(PackageDescription("Pack.Age", dependencies: new[] { @@ -225,18 +245,16 @@ namespace Microsoft.Extensions.DependencyModel.Tests private LibraryExport Export( LibraryDescription description, IEnumerable compilationAssemblies = null, - IEnumerable runtimeAssemblies = null) + IEnumerable runtimeAssemblies = null, + IEnumerable runtimeTargets = null, + IEnumerable resourceAssemblies = null) { - return new LibraryExport( - description, - compilationAssemblies ?? Enumerable.Empty(), - Enumerable.Empty(), - runtimeAssemblies ?? Enumerable.Empty(), - Enumerable.Empty(), - Enumerable.Empty(), - Enumerable.Empty(), - Enumerable.Empty() - ); + return LibraryExportBuilder.Create(description) + .WithCompilationAssemblies(compilationAssemblies) + .WithRuntimeAssemblies(runtimeAssemblies) + .WithRuntimeTargets(runtimeTargets) + .WithResourceAssemblies(resourceAssemblies) + .Build(); } private PackageDescription PackageDescription( diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs index b5fb29a10..b48d812e5 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs @@ -183,6 +183,9 @@ namespace Microsoft.Extensions.DependencyModel.Tests ""runtimeTargets"": { ""lib/win7/System.Banana.dll"": { ""assetType"": ""runtime"", ""rid"": ""win7-x64""}, ""lib/win7/Banana.dll"": { ""assetType"": ""native"", ""rid"": ""win7-x64""} + }, + ""resources"": { + ""System.Banana.resources.dll"": { ""locale"": ""en-US"" } } } } @@ -211,6 +214,8 @@ namespace Microsoft.Extensions.DependencyModel.Tests package.Type.Should().Be("package"); package.Serviceable.Should().Be(false); package.Assemblies.Should().Contain(a => a.Path == "lib/dotnet5.4/System.Banana.dll"); + package.ResourceAssemblies.Should().Contain(a => a.Path == "System.Banana.resources.dll") + .Subject.Locale.Should().Be("en-US"); var target = package.RuntimeTargets.Should().Contain(t => t.Runtime == "win7-x64").Subject; target.Assemblies.Should().Contain(a => a.Path == "lib/win7/System.Banana.dll"); diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs index 0e1639fde..2c0b76840 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs @@ -154,6 +154,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests "1.2.3", "HASH", new [] { RuntimeAssembly.Create("Banana.dll")}, + new [] { new ResourceAssembly("en-US\\Banana.Resource.dll", "en-US")}, new [] { new RuntimeTarget("win7-x64", @@ -187,6 +188,10 @@ namespace Microsoft.Extensions.DependencyModel.Tests nativeLibrary.Should().HavePropertyValue("rid", "win7-x64"); nativeLibrary.Should().HavePropertyValue("assetType", "native"); + var resourceAssemblies = library.Should().HavePropertyAsObject("resources").Subject; + var resourceAssembly = resourceAssemblies.Should().HavePropertyAsObject("en-US\\Banana.Resource.dll").Subject; + resourceAssembly.Should().HavePropertyValue("locale", "en-US"); + //libraries var libraries = result.Should().HavePropertyAsObject("libraries").Subject; library = libraries.Should().HavePropertyAsObject("PackageName/1.2.3").Subject; @@ -224,6 +229,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests "1.2.3", "HASH", new [] { RuntimeAssembly.Create("Banana.dll")}, + new ResourceAssembly[] {}, new [] { new RuntimeTarget("win7-x64", @@ -283,6 +289,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests "1.2.3", "HASH", new [] { RuntimeAssembly.Create("Banana.dll")}, + new ResourceAssembly[] {}, new RuntimeTarget[] {}, new [] { new Dependency("Fruits.Abstract.dll","2.0.0") @@ -308,6 +315,74 @@ namespace Microsoft.Extensions.DependencyModel.Tests library.Should().HavePropertyValue("serviceable", true); } + [Fact] + public void WritesResourceAssembliesForNonPortable() + { + var result = Save(Create( + "Target", + "runtime", + false, + runtimeLibraries: new[] + { + new RuntimeLibrary( + "package", + "PackageName", + "1.2.3", + "HASH", + new RuntimeAssembly[] { }, + new [] + { + new ResourceAssembly("en-US/Fruits.resources.dll", "en-US") + }, + new RuntimeTarget[] { }, + new Dependency[] { }, + true + ), + })); + + var targets = result.Should().HavePropertyAsObject("targets").Subject; + var target = targets.Should().HavePropertyAsObject("Target/runtime").Subject; + var library = target.Should().HavePropertyAsObject("PackageName/1.2.3").Subject; + var resources = library.Should().HavePropertyAsObject("resources").Subject; + var resource = resources.Should().HavePropertyAsObject("en-US/Fruits.resources.dll").Subject; + resource.Should().HavePropertyValue("locale", "en-US"); + } + + + [Fact] + public void WritesResourceAssembliesForPortable() + { + var result = Save(Create( + "Target", + "runtime", + true, + runtimeLibraries: new[] + { + new RuntimeLibrary( + "package", + "PackageName", + "1.2.3", + "HASH", + new RuntimeAssembly[] { }, + new [] + { + new ResourceAssembly("en-US/Fruits.resources.dll", "en-US") + }, + new RuntimeTarget[] { }, + new Dependency[] { }, + true + ), + })); + + var targets = result.Should().HavePropertyAsObject("targets").Subject; + var target = targets.Should().HavePropertyAsObject("Target").Subject; + var library = target.Should().HavePropertyAsObject("PackageName/1.2.3").Subject; + var resources = library.Should().HavePropertyAsObject("resources").Subject; + var resource = resources.Should().HavePropertyAsObject("en-US/Fruits.resources.dll").Subject; + resource.Should().HavePropertyValue("locale", "en-US"); + } + + [Fact] public void WritesCompilationOptions() { From 7b84740e72275cdaad8aee84af254b13a9f4a387 Mon Sep 17 00:00:00 2001 From: Andrew Stanton-Nurse Date: Tue, 8 Mar 2016 12:14:59 -0800 Subject: [PATCH 09/31] reremove net45 build from portable app test project this somehow got restored during a bad merge, and is breaking the CI --- TestAssets/TestProjects/BuildTestPortableProject/project.json | 1 - 1 file changed, 1 deletion(-) diff --git a/TestAssets/TestProjects/BuildTestPortableProject/project.json b/TestAssets/TestProjects/BuildTestPortableProject/project.json index 43c20c90b..841c77d4d 100644 --- a/TestAssets/TestProjects/BuildTestPortableProject/project.json +++ b/TestAssets/TestProjects/BuildTestPortableProject/project.json @@ -2,7 +2,6 @@ "dependencies": { }, "frameworks": { - "net45": {}, "netstandardapp1.5": { "imports": [ "dnxcore50", From 12dd8d611286f8fb88791b76b4bca97475e71d8e Mon Sep 17 00:00:00 2001 From: Andrew Stanton-Nurse Date: Tue, 8 Mar 2016 14:44:53 -0800 Subject: [PATCH 10/31] fix bad merge that lost removal of net45 from portable app test --- test/dotnet-build.Tests/BuildPortableTests.cs | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/test/dotnet-build.Tests/BuildPortableTests.cs b/test/dotnet-build.Tests/BuildPortableTests.cs index 6ecfad1f1..83e1e8544 100644 --- a/test/dotnet-build.Tests/BuildPortableTests.cs +++ b/test/dotnet-build.Tests/BuildPortableTests.cs @@ -22,23 +22,15 @@ namespace Microsoft.DotNet.Tools.Builder.Tests var outputBase = new DirectoryInfo(Path.Combine(testInstance.TestRoot, "bin", "Debug")); var netstandardappOutput = outputBase.Sub("netstandardapp1.5"); - var fxSubdirs = new[] { - netstandardappOutput, - outputBase.Sub("net45") - }; - foreach(var fxSubdir in fxSubdirs) - { - fxSubdir.Should() - .Exist().And - .HaveFiles(new[] - { - "BuildTestPortableProject.dll", - "BuildTestPortableProject.pdb" - }); - } - - netstandardappOutput.Should().HaveFile("BuildTestPortableProject.deps"); + netstandardappOutput.Should() + .Exist().And + .HaveFiles(new[] + { + "BuildTestPortableProject.deps", + "BuildTestPortableProject.dll", + "BuildTestPortableProject.pdb" + }); } } } From ae041c8f612bebec56255ed6abad0a95ff8aa875 Mon Sep 17 00:00:00 2001 From: Sridhar Periyasamy Date: Mon, 7 Mar 2016 14:52:41 -0800 Subject: [PATCH 11/31] Address some PR feedback. - Make the MSI scripts to use parameters instead of environment variables. --- packaging/windows/generatebundle.ps1 | 14 ++++++--- packaging/windows/generatemsi.ps1 | 19 ++++++------ .../TargetConditions/EnvironmentAttribute.cs | 17 +++++----- scripts/dotnet-cli-build/MsiTargets.cs | 31 ++++++++++++------- scripts/dotnet-cli-build/PackageTargets.cs | 2 +- scripts/dotnet-cli-build/PrepareTargets.cs | 11 ++++--- scripts/dotnet-cli-build/PublishTargets.cs | 5 +-- scripts/run-build.sh | 3 +- 8 files changed, 58 insertions(+), 44 deletions(-) diff --git a/packaging/windows/generatebundle.ps1 b/packaging/windows/generatebundle.ps1 index 0b528bc13..e50300363 100644 --- a/packaging/windows/generatebundle.ps1 +++ b/packaging/windows/generatebundle.ps1 @@ -4,7 +4,11 @@ param( [Parameter(Mandatory=$true)][string]$DotnetMSIFile, [Parameter(Mandatory=$true)][string]$DotnetBundleOutput, - [Parameter(Mandatory=$true)][string]$WixRoot + [Parameter(Mandatory=$true)][string]$WixRoot, + [Parameter(Mandatory=$true)][string]$DotnetMSIVersion, + [Parameter(Mandatory=$true)][string]$DotnetCLIVersion, + [Parameter(Mandatory=$true)][string]$Architecture, + [Parameter(Mandatory=$true)][string]$ReleaseSuffix ) . "$PSScriptRoot\..\..\scripts\common\_common.ps1" @@ -21,11 +25,11 @@ function RunCandleForBundle .\candle.exe -nologo ` -dDotnetSrc="$inputDir" ` -dMicrosoftEula="$RepoRoot\packaging\osx\resources\en.lproj\eula.rtf" ` - -dBuildVersion="$env:DOTNET_MSI_VERSION" ` - -dDisplayVersion="$env:DOTNET_CLI_VERSION" ` - -dReleaseSuffix="$env:ReleaseSuffix" ` + -dBuildVersion="$DotnetMSIVersion" ` + -dDisplayVersion="$DotnetCLIVersion" ` + -dReleaseSuffix="$ReleaseSuffix" ` -dMsiSourcePath="$DotnetMSIFile" ` - -arch "$env:ARCHITECTURE" ` + -arch "$Architecture" ` -ext WixBalExtension.dll ` -ext WixUtilExtension.dll ` -ext WixTagExtension.dll ` diff --git a/packaging/windows/generatemsi.ps1 b/packaging/windows/generatemsi.ps1 index 693e1396c..54a6a9388 100644 --- a/packaging/windows/generatemsi.ps1 +++ b/packaging/windows/generatemsi.ps1 @@ -4,7 +4,11 @@ param( [Parameter(Mandatory=$true)][string]$inputDir, [Parameter(Mandatory=$true)][string]$DotnetMSIOutput, - [Parameter(Mandatory=$true)][string]$WixRoot + [Parameter(Mandatory=$true)][string]$WixRoot, + [Parameter(Mandatory=$true)][string]$DotnetMSIVersion, + [Parameter(Mandatory=$true)][string]$DotnetCLIVersion, + [Parameter(Mandatory=$true)][string]$Architecture, + [Parameter(Mandatory=$true)][string]$ReleaseSuffix ) . "$PSScriptRoot\..\..\scripts\common\_common.ps1" @@ -43,10 +47,10 @@ function RunCandle .\candle.exe -nologo ` -dDotnetSrc="$inputDir" ` -dMicrosoftEula="$RepoRoot\packaging\osx\resources\en.lproj\eula.rtf" ` - -dBuildVersion="$env:DOTNET_MSI_VERSION" ` - -dDisplayVersion="$env:DOTNET_CLI_VERSION" ` - -dReleaseSuffix="$env:ReleaseSuffix" ` - -arch "$env:ARCHITECTURE" ` + -dBuildVersion="$DotnetMSIVersion" ` + -dDisplayVersion="$DotnetCLIVersion" ` + -dReleaseSuffix="$ReleaseSuffix" ` + -arch "$Architecture" ` -ext WixDependencyExtension.dll ` "$AuthWsxRoot\dotnet.wxs" ` "$AuthWsxRoot\provider.wxs" ` @@ -101,11 +105,6 @@ if(!(Test-Path $inputDir)) throw "$inputDir not found" } -if(!(Test-Path $PackageDir)) -{ - mkdir $PackageDir | Out-Null -} - Write-Host "Creating dotnet MSI at $DotnetMSIOutput" if([string]::IsNullOrEmpty($WixRoot)) diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/EnvironmentAttribute.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/EnvironmentAttribute.cs index 473aff2da..2a9aea581 100644 --- a/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/EnvironmentAttribute.cs +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/EnvironmentAttribute.cs @@ -7,9 +7,9 @@ namespace Microsoft.DotNet.Cli.Build.Framework public class EnvironmentAttribute : TargetConditionAttribute { private string _envVar; - private string _expectedVal; + private string[] _expectedVals; - public EnvironmentAttribute(string envVar, string expectedVal) + public EnvironmentAttribute(string envVar, params string[] expectedVals) { if (string.IsNullOrEmpty(envVar)) { @@ -17,21 +17,22 @@ namespace Microsoft.DotNet.Cli.Build.Framework } _envVar = envVar; - _expectedVal = expectedVal; + _expectedVals = expectedVals; } public override bool EvaluateCondition() { var actualVal = Environment.GetEnvironmentVariable(_envVar); - if (string.IsNullOrEmpty(_expectedVal)) + foreach (var expectedVal in _expectedVals) { - return string.IsNullOrEmpty(actualVal) || - actualVal.Equals("0") || - actualVal.ToLower().Equals("false"); + if (string.Equals(actualVal, expectedVal, StringComparison.Ordinal)) + { + return true; + } } - return _expectedVal.Equals(actualVal, StringComparison.Ordinal); + return false; } } } diff --git a/scripts/dotnet-cli-build/MsiTargets.cs b/scripts/dotnet-cli-build/MsiTargets.cs index 57120cdf5..6d83a8794 100644 --- a/scripts/dotnet-cli-build/MsiTargets.cs +++ b/scripts/dotnet-cli-build/MsiTargets.cs @@ -28,6 +28,14 @@ namespace Microsoft.DotNet.Cli.Build private static string Engine { get; set; } + private static string MsiVersion { get; set; } + + private static string CliVersion { get; set; } + + private static string Arch { get; } = CurrentArchitecture.Current.ToString(); + + private static string Channel { get; set; } + private static void AcquireWix(BuildTargetContext c) { if (File.Exists(Path.Combine(WixRoot, "candle.exe"))) @@ -55,6 +63,12 @@ namespace Microsoft.DotNet.Cli.Build Bundle = c.BuildContext.Get("InstallerFile"); Msi = Path.ChangeExtension(Bundle, "msi"); Engine = Path.Combine(Path.GetDirectoryName(Bundle), ENGINE); + + var buildVersion = c.BuildContext.Get("BuildVersion"); + MsiVersion = buildVersion.GenerateMsiVersion(); + CliVersion = buildVersion.SimpleVersion; + Channel = c.BuildContext.Get("Channel"); + AcquireWix(c); return c.Success(); } @@ -66,12 +80,6 @@ namespace Microsoft.DotNet.Cli.Build [BuildPlatforms(BuildPlatform.Windows)] public static BuildTargetResult GenerateMsis(BuildTargetContext c) { - var env = PackageTargets.GetCommonEnvVars(c); - Cmd("powershell", "-NoProfile", "-NoLogo", - Path.Combine(Dirs.RepoRoot, "packaging", "windows", "generatemsi.ps1"), Dirs.Stage2, Msi, WixRoot) - .Environment(env) - .Execute() - .EnsureSuccessful(); return c.Success(); } @@ -79,10 +87,9 @@ namespace Microsoft.DotNet.Cli.Build [BuildPlatforms(BuildPlatform.Windows)] public static BuildTargetResult GenerateCLISDKMsi(BuildTargetContext c) { - var env = PackageTargets.GetCommonEnvVars(c); Cmd("powershell", "-NoProfile", "-NoLogo", - Path.Combine(Dirs.RepoRoot, "packaging", "windows", "generatemsi.ps1"), Dirs.Stage2, Msi, WixRoot) - .Environment(env) + Path.Combine(Dirs.RepoRoot, "packaging", "windows", "generatemsi.ps1"), + Dirs.Stage2, Msi, WixRoot, MsiVersion, CliVersion, Arch, Channel) .Execute() .EnsureSuccessful(); return c.Success(); @@ -107,10 +114,10 @@ namespace Microsoft.DotNet.Cli.Build [BuildPlatforms(BuildPlatform.Windows)] public static BuildTargetResult GenerateBundle(BuildTargetContext c) { - var env = PackageTargets.GetCommonEnvVars(c); Cmd("powershell", "-NoProfile", "-NoLogo", - Path.Combine(Dirs.RepoRoot, "packaging", "windows", "generatebundle.ps1"), Msi, Bundle, WixRoot) - .Environment(env) + Path.Combine(Dirs.RepoRoot, "packaging", "windows", "generatebundle.ps1"), + Msi, Bundle, WixRoot, MsiVersion, CliVersion, Arch, Channel) + .EnvironmentVariable("Stage2Dir", Dirs.Stage2) .Execute() .EnsureSuccessful(); return c.Success(); diff --git a/scripts/dotnet-cli-build/PackageTargets.cs b/scripts/dotnet-cli-build/PackageTargets.cs index c0c369be2..c43b201e1 100644 --- a/scripts/dotnet-cli-build/PackageTargets.cs +++ b/scripts/dotnet-cli-build/PackageTargets.cs @@ -25,7 +25,7 @@ namespace Microsoft.DotNet.Cli.Build nameof(PackageTargets.GenerateCompressedFile), nameof(InstallerTargets.GenerateInstaller), nameof(PackageTargets.GenerateNugetPackages))] - [Environment("DOTNET_BUILD_SKIP_PACKAGING", null)] + [Environment("DOTNET_BUILD_SKIP_PACKAGING", null, "0", "false")] public static BuildTargetResult Package(BuildTargetContext c) { return c.Success(); diff --git a/scripts/dotnet-cli-build/PrepareTargets.cs b/scripts/dotnet-cli-build/PrepareTargets.cs index 801f15ac7..9a11d5b7e 100644 --- a/scripts/dotnet-cli-build/PrepareTargets.cs +++ b/scripts/dotnet-cli-build/PrepareTargets.cs @@ -21,10 +21,10 @@ namespace Microsoft.DotNet.Cli.Build [Target(nameof(CheckPrereqCmakePresent), nameof(CheckPlatformDependencies))] public static BuildTargetResult CheckPrereqs(BuildTargetContext c) => c.Success(); - [Target(nameof(CheckCoreclrPlatformDependencies), nameof(CheckInstallerBuildPlatformDependencies))] + [Target(nameof(CheckCoreclrPlatformDependencies), nameof(CheckInstallerBuildPlatformDependencies))] public static BuildTargetResult CheckPlatformDependencies(BuildTargetContext c) => c.Success(); - [Target(nameof(CheckUbuntuCoreclrAndCoreFxDependencies), nameof(CheckCentOSCoreclrAndCoreFxDependencies))] + [Target(nameof(CheckUbuntuCoreclrAndCoreFxDependencies), nameof(CheckCentOSCoreclrAndCoreFxDependencies))] public static BuildTargetResult CheckCoreclrPlatformDependencies(BuildTargetContext c) => c.Success(); [Target(nameof(CheckUbuntuDebianPackageBuildDependencies))] @@ -44,6 +44,7 @@ namespace Microsoft.DotNet.Cli.Build } c.BuildContext["Configuration"] = configEnv; + c.BuildContext["Channel"] = Environment.GetEnvironmentVariable("CHANNEL"); c.Info($"Building {c.BuildContext["Configuration"]} to: {Dirs.Output}"); c.Info("Build Environment:"); @@ -116,7 +117,7 @@ namespace Microsoft.DotNet.Cli.Build c.BuildContext["CompressedFile"] = Path.Combine(Dirs.Packages, productName + extension); string installer = ""; - switch(CurrentPlatform.Current) + switch (CurrentPlatform.Current) { case BuildPlatform.Windows: installer = productName + ".exe"; @@ -131,7 +132,7 @@ namespace Microsoft.DotNet.Cli.Build break; } - if(!string.IsNullOrEmpty(installer)) + if (!string.IsNullOrEmpty(installer)) { c.BuildContext["InstallerFile"] = Path.Combine(Dirs.Packages, installer); } @@ -279,7 +280,7 @@ namespace Microsoft.DotNet.Cli.Build public static BuildTargetResult CheckCentOSCoreclrAndCoreFxDependencies(BuildTargetContext c) { var errorMessageBuilder = new StringBuilder(); - + foreach (var package in PackageDependencies.CentosCoreclrAndCoreFxDependencies) { if (!YumDependencyUtility.PackageIsInstalled(package)) diff --git a/scripts/dotnet-cli-build/PublishTargets.cs b/scripts/dotnet-cli-build/PublishTargets.cs index df0309564..a441ecd99 100644 --- a/scripts/dotnet-cli-build/PublishTargets.cs +++ b/scripts/dotnet-cli-build/PublishTargets.cs @@ -17,7 +17,7 @@ namespace Microsoft.DotNet.Cli.Build { private static CloudBlobContainer BlobContainer { get; set; } - private static string Channel { get; } = "Test";// Environment.GetEnvironmentVariable("RELEASE_SUFFIX"); + private static string Channel { get; set; } private static string Version { get; set; } @@ -30,13 +30,14 @@ namespace Microsoft.DotNet.Cli.Build BlobContainer = blobClient.GetContainerReference("dotnet"); Version = c.BuildContext.Get("BuildVersion").SimpleVersion; + Channel = c.BuildContext.Get("Channel"); return c.Success(); } [Target(nameof(PrepareTargets.Init), nameof(PublishTargets.InitPublish), nameof(PublishTargets.PublishArtifacts))] - [Environment("PUBLISH_TO_AZURE_BLOB", "true")] // This is set by CI systems + [Environment("PUBLISH_TO_AZURE_BLOB", "1", "true")] // This is set by CI systems public static BuildTargetResult Publish(BuildTargetContext c) { return c.Success(); diff --git a/scripts/run-build.sh b/scripts/run-build.sh index 2fe9811e0..6d911028b 100755 --- a/scripts/run-build.sh +++ b/scripts/run-build.sh @@ -82,7 +82,8 @@ done < "$DIR/../branchinfo.txt" [ -d $DOTNET_INSTALL_DIR ] || mkdir -p $DOTNET_INSTALL_DIR # Ensure the latest stage0 is installed -$DIR/obtain/install.sh --channel $RELEASE_SUFFIX +export CHANNEL=$RELEASE_SUFFIX +$DIR/obtain/install.sh --channel $CHANNEL # Put stage 0 on the PATH (for this shell only) PATH="$DOTNET_INSTALL_DIR/bin:$PATH" From 015bda2137c83fa25f613d1a5d3349e63c714a12 Mon Sep 17 00:00:00 2001 From: Sridhar Periyasamy Date: Tue, 8 Mar 2016 23:33:18 +0000 Subject: [PATCH 12/31] Debian package and publish changes - Use parameters instead of env vars to create debian packages. - Target to publish the deb package to the debian repo. --- scripts/dotnet-cli-build/InstallerTargets.cs | 11 +- scripts/dotnet-cli-build/PublishTargets.cs | 38 +++ scripts/dotnet-cli-build/Utils/Monikers.cs | 23 ++ scripts/package/package-debian.sh | 83 ++++-- scripts/publish/publish.sh | 246 ------------------ .../test/integration_tests/test_package.bats | 9 + 6 files changed, 134 insertions(+), 276 deletions(-) delete mode 100755 scripts/publish/publish.sh diff --git a/scripts/dotnet-cli-build/InstallerTargets.cs b/scripts/dotnet-cli-build/InstallerTargets.cs index 81068ade0..7f1fa1649 100644 --- a/scripts/dotnet-cli-build/InstallerTargets.cs +++ b/scripts/dotnet-cli-build/InstallerTargets.cs @@ -40,9 +40,14 @@ namespace Microsoft.DotNet.Cli.Build [BuildPlatforms(BuildPlatform.Ubuntu)] public static BuildTargetResult GenerateDeb(BuildTargetContext c) { - var env = PackageTargets.GetCommonEnvVars(c); - Cmd(Path.Combine(Dirs.RepoRoot, "scripts", "package", "package-debian.sh")) - .Environment(env) + var channel = c.BuildContext.Get("Channel").ToLower(); + var packageName = Monikers.GetDebianPackageName(c); + var version = c.BuildContext.Get("BuildVersion").SimpleVersion; + var debFile = c.BuildContext.Get("InstallerFile"); + var manPagesDir = Path.Combine(Dirs.RepoRoot, "Documentation", "manpages"); + + Cmd(Path.Combine(Dirs.RepoRoot, "scripts", "package", "package-debian.sh"), + "-v", version, "-i", Dirs.Stage2, "-o", debFile, "-p", packageName, "-m", manPagesDir, "-c", channel) .Execute() .EnsureSuccessful(); return c.Success(); diff --git a/scripts/dotnet-cli-build/PublishTargets.cs b/scripts/dotnet-cli-build/PublishTargets.cs index a441ecd99..6a69fcd89 100644 --- a/scripts/dotnet-cli-build/PublishTargets.cs +++ b/scripts/dotnet-cli-build/PublishTargets.cs @@ -102,6 +102,44 @@ namespace Microsoft.DotNet.Cli.Build return c.Success(); } + [Target(nameof(PublishInstallerFile))] + [BuildPlatforms(BuildPlatform.Ubuntu)] + public static BuildTargetResult PublishDebFileToDebianRepo(BuildTargetContext c) + { + var packageName = Monikers.GetDebianPackageName(c); + var installerFile = c.BuildContext.Get("InstallerFile"); + var uploadUrl = $"https://dotnetcli.blob.core.windows.net/dotnet/{Channel}/Installers/{Version}/{Path.GetFileName(installerFile)}"; + var uploadJson = GenerateUploadJsonFile(packageName, Version, uploadUrl); + + Cmd(Path.Combine(Dirs.RepoRoot, "scripts", "publish", "repoapi_client.sh"), "-addpkg", uploadJson) + .Execute() + .EnsureSuccessful(); + + return c.Success(); + } + + private static string GenerateUploadJsonFile(string packageName, string version, string uploadUrl) + { + var repoID = Environment.GetEnvironmentVariable("REPO_ID"); + var uploadJson = Path.Combine(Dirs.Packages, "package_upload.json"); + File.Delete(uploadJson); + + using (var fileStream = File.Create(uploadJson)) + { + using (StreamWriter sw = new StreamWriter(fileStream)) + { + sw.WriteLine("{"); + sw.WriteLine($" \"name\":\"{packageName}\","); + sw.WriteLine($" \"version\":\"{version}\","); + sw.WriteLine($" \"repositoryId\":\"{repoID}\","); + sw.WriteLine($" \"sourceUrl\":\"{uploadUrl}\""); + sw.WriteLine("}"); + } + } + + return uploadJson; + } + private static BuildTargetResult PublishFile(BuildTargetContext c, string file) { var env = PackageTargets.GetCommonEnvVars(c); diff --git a/scripts/dotnet-cli-build/Utils/Monikers.cs b/scripts/dotnet-cli-build/Utils/Monikers.cs index 0940a40d6..522de0f05 100644 --- a/scripts/dotnet-cli-build/Utils/Monikers.cs +++ b/scripts/dotnet-cli-build/Utils/Monikers.cs @@ -16,6 +16,29 @@ namespace Microsoft.DotNet.Cli.Build return $"dotnet-{osname}-{arch}.{version}"; } + public static string GetDebianPackageName(BuildTargetContext c) + { + var channel = c.BuildContext.Get("Channel").ToLower(); + var packageName = ""; + switch (channel) + { + case "dev": + packageName = "dotnet-nightly"; + break; + case "beta": + case "rc1": + case "rc2": + case "rtm": + packageName = "dotnet"; + break; + default: + throw new Exception($"Unknown channel - {channel}"); + break; + } + + return packageName; + } + public static string GetOSShortName() { string osname = ""; diff --git a/scripts/package/package-debian.sh b/scripts/package/package-debian.sh index 0db47aca6..f8cbcc0e9 100755 --- a/scripts/package/package-debian.sh +++ b/scripts/package/package-debian.sh @@ -17,46 +17,73 @@ done DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" source "$DIR/../common/_common.sh" +REPOROOT="$DIR/../.." -if [ "$OSNAME" != "ubuntu" ]; then - error "Debian Package build only supported on Ubuntu" +help(){ + echo "Usage: $0" + echo "" + echo "Options:" + echo " --version Specify a version for the package." + echo " --input Package the entire contents of the directory tree." + echo " --manpages Directory containing man pages for the package." + echo " --output The full path to which the package will be written." + echo " --package-name Package to identify during installation. Example - 'dotnet-nightly', 'dotnet'" + echo " --channel Channel against which to run the upgrade tests. Example - 'dev', 'beta'" exit 1 -fi +} + +while [[ $# > 0 ]]; do + lowerI="$(echo $1 | awk '{print tolower($0)}')" + echo "$lowerI" + case $lowerI in + -m|--manpages) + MANPAGE_DIR=$2 + shift + ;; + -o|--output) + OUTPUT_DEBIAN_FILE=$2 + shift + ;; + -i|--input) + REPO_BINARIES_DIR=$2 + shift + ;; + -p|--package-name) + DOTNET_DEB_PACKAGE_NAME=$2 + shift + ;; + -v|--version) + DOTNET_CLI_VERSION=$2 + shift + ;; + -c|--channel) + CHANNEL=$2 + shift + ;; + --help) + help + ;; + *) + echo $lowerI + break + ;; + esac + shift +done PACKAGING_ROOT="$REPOROOT/packaging/debian" PACKAGING_TOOL_DIR="$REPOROOT/tools/DebianPackageTool" -OUTPUT_DIR="$REPOROOT/artifacts" -PACKAGE_LAYOUT_DIR="$OUTPUT_DIR/deb_intermediate" -PACKAGE_OUTPUT_DIR="$OUTPUT_DIR/packages/debian" -TEST_STAGE_DIR="$PACKAGE_OUTPUT_DIR/test" -REPO_BINARIES_DIR="$REPOROOT/artifacts/ubuntu.14.04-x64/stage2" -MANPAGE_DIR="$REPOROOT/Documentation/manpages" - -NIGHTLY_PACKAGE_NAME="dotnet-nightly" -RELEASE_PACKAGE_NAME="dotnet" - -[ -z "$CHANNEL" ] && CHANNEL="dev" +PACKAGE_OUTPUT_DIR=$(dirname "${OUTPUT_DEBIAN_FILE}") +PACKAGE_LAYOUT_DIR="$PACKAGE_OUTPUT_DIR/deb_intermediate" +TEST_STAGE_DIR="$PACKAGE_OUTPUT_DIR/debian_tests" execute_build(){ - determine_package_name create_empty_debian_layout copy_files_to_debian_layout create_debian_package } -determine_package_name(){ - if [[ "$RELEASE_SUFFIX" == "dev" ]]; then - DOTNET_DEB_PACKAGE_NAME=$NIGHTLY_PACKAGE_NAME - elif [[ "beta rc1 rc2 rtm" =~ (^| )"$RELEASE_SUFFIX"($| ) ]]; then - DOTNET_DEB_PACKAGE_NAME=$RELEASE_PACKAGE_NAME - elif [[ "$RELEASE_SUFFIX" == "" ]]; then - DOTNET_DEB_PACKAGE_NAME=$RELEASE_PACKAGE_NAME - else - DOTNET_DEB_PACKAGE_NAME=$NIGHTLY_PACKAGE_NAME - fi -} - execute_test(){ test_debian_package } @@ -138,6 +165,8 @@ run_e2e_test(){ execute_build +rm -f "$OUTPUT_DEBIAN_FILE" DEBIAN_FILE=$(find $PACKAGE_OUTPUT_DIR -iname "*.deb") +mv -f "$DEBIAN_FILE" "$OUTPUT_DEBIAN_FILE" execute_test diff --git a/scripts/publish/publish.sh b/scripts/publish/publish.sh deleted file mode 100755 index 743815f08..000000000 --- a/scripts/publish/publish.sh +++ /dev/null @@ -1,246 +0,0 @@ -#!/bin/bash -# -# Copyright (c) .NET Foundation and contributors. All rights reserved. -# Licensed under the MIT license. See LICENSE file in the project root for full license information. -# - -# Usage: publish.sh [file to be uploaded] -# -# Environment Dependencies: -# $STORAGE_CONTAINER -# $STORAGE_ACCOUNT -# $SASTOKEN -# $REPO_ID - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -source "$DIR/../common/_common.sh" - -SCRIPT_DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -UPLOAD_FILE=$1 -UPLOAD_JSON_FILE="package_upload.json" - -header "Publishing package" - -execute(){ - if ! validate_env_variables; then - # fail silently if the required variables are not available for publishing the file. - exit 0 - fi - - if [[ ! -f "$UPLOAD_FILE" ]]; then - error "\"$UPLOAD_FILE\" file does not exist" - exit 1 - fi - - if [[ $UPLOAD_FILE == *.deb || $UPLOAD_FILE == *.pkg ]]; then - upload_installers_to_blob_storage $UPLOAD_FILE - result=$? - elif [[ $UPLOAD_FILE == *.tar.gz ]]; then - upload_binaries_to_blob_storage $UPLOAD_FILE - result=$? - elif [[ $UPLOAD_FILE == *.svg ]]; then - upload_version_badge $UPLOAD_FILE - result=$? - fi - - exit $result -} - -validate_env_variables(){ - local ret=0 - - if [[ -z "$DOTNET_CLI_VERSION" ]]; then - warning "DOTNET_CLI_VERSION environment variable not set" - ret=1 - fi - - if [[ -z "$SASTOKEN" ]]; then - warning "SASTOKEN environment variable not set" - ret=1 - fi - - if [[ -z "$STORAGE_ACCOUNT" ]]; then - warning "STORAGE_ACCOUNT environment variable not set" - ret=1 - fi - - if [[ -z "$STORAGE_CONTAINER" ]]; then - warning "STORAGE_CONTAINER environment variable not set" - ret=1 - fi - - if [[ -z "$CHANNEL" ]]; then - warning "CHANNEL environment variable not set" - ret=1 - fi - - if [[ -z "$CONNECTION_STRING" ]]; then - warning "CONNECTION_STRING environment variable not set" - ret=1 - fi - - return $ret -} - -upload_file_to_blob_storage_azure_cli(){ - local blob=$1 - local file=$2 - local preventCaching=${3:false} - - header "Uploading $file to blob storage" - - local properties="" - - if $preventCaching ; then - properties="--properties cacheControl=no-cache" - fi - - # use azure cli to upload to blob storage. We cannot use curl to do this becuase azure has a max limit of 64mb that can be uploaded using REST - # statusCode=$(curl -s -w "%{http_code}" -L -H "x-ms-blob-type: BlockBlob" -H "x-ms-date: 2015-10-21" -H "x-ms-version: 2013-08-15" $upload_URL -T $file) - azure storage blob upload --quiet $properties --container $STORAGE_CONTAINER --blob $blob --blobtype block --connection-string "$CONNECTION_STRING" --file $file - result=$? - - if [ "$result" -eq "0" ]; then - info "successfully uploaded $filename to blob storage." - return 0 - else - error "uploading the $filename to blob storage - $statusCode" - return 1 - fi -} - -update_file_in_blob_storage(){ - local update_URL=$1 - local file=$2 - local filecontent=$3 - - header "Updating $file in blob storage" - - statusCode=$(curl -s -w "%{http_code}" -L -H "x-ms-blob-type: BlockBlob" -H "x-ms-date: 2015-10-21" -H "x-ms-version: 2013-08-15" -H "Content-Type: text/plain" $update_URL --data-binary $filecontent --request PUT ) - - if [ "$statusCode" -eq "201" ]; then - info "successfully updated $file in blob storage." - return 0 - else - error "updating the $file in blob storage - $statusCode" - return 1 - fi -} - -upload_binaries_to_blob_storage(){ - local tarfile=$1 - local filename=$(basename $tarfile) - local blob="$CHANNEL/Binaries/$DOTNET_CLI_VERSION/$filename" - - if ! upload_file_to_blob_storage_azure_cli $blob $tarfile; then - return 1 - fi - - # create the latest blob - echo "Updating the latest dotnet binaries.." - local latestblob="$CHANNEL/Binaries/Latest/dotnet-$OSNAME-x64.latest.tar.gz" - - if ! upload_file_to_blob_storage_azure_cli $latestblob $tarfile true; then - return 1 - fi - - # update the index file - local indexContent="Binaries/$DOTNET_CLI_VERSION/$filename" - local indexfile="latest.$OSNAME.index" - local index_URL="https://$STORAGE_ACCOUNT.blob.core.windows.net/$STORAGE_CONTAINER/$CHANNEL/dnvm/$indexfile$SASTOKEN" - update_file_in_blob_storage $index_URL $indexfile $indexContent true - - # update the version file - # the "@" prefix tells curl to upload the content of the file - local versionContent="@$REPOROOT/artifacts/$RID/stage2/.version" - local versionfile="latest.$OSNAME.version" - local version_URL="https://$STORAGE_ACCOUNT.blob.core.windows.net/$STORAGE_CONTAINER/$CHANNEL/dnvm/$versionfile$SASTOKEN" - update_file_in_blob_storage $version_URL $versionfile $versionContent true - - return $? -} - -upload_installers_to_blob_storage(){ - local installfile=$1 - local filename=$(basename $installfile) - local blob="$CHANNEL/Installers/$DOTNET_CLI_VERSION/$filename" - - if ! upload_file_to_blob_storage_azure_cli $blob $installfile; then - return 1 - fi - - # create the latest blob - echo "Updating the latest dotnet installer.." - local extension="${filename##*.}" - local latestblob="$CHANNEL/Installers/Latest/dotnet-$OSNAME-x64.latest.$extension" - - if ! upload_file_to_blob_storage_azure_cli $latestblob $installfile true; then - return 1 - fi - - # debain packages need to be uploaded to the PPA feed too - if [[ $installfile == *.deb ]]; then - DEB_FILE=$installfile - UPLOAD_URL="https://$STORAGE_ACCOUNT.blob.core.windows.net/$STORAGE_CONTAINER/$blob" - generate_repoclient_json - call_repo_client - fi - - return 0 -} - -upload_version_badge(){ - local badgefile=$1 - local filename="${OSNAME}_${CONFIGURATION}_$(basename $badgefile)" - echo "Uploading the version badge to Latest" - upload_file_to_blob_storage_azure_cli "$CHANNEL/Binaries/Latest/$filename" $badgefile true - - echo "Uploading the version badge to $DOTNET_CLI_VERSION" - upload_file_to_blob_storage_azure_cli "$CHANNEL/Binaries/$DOTNET_CLI_VERSION/$filename" $badgefile - - return 0 -} - - -generate_repoclient_json(){ - # Clean any existing json file - rm -f $SCRIPT_DIR/$UPLOAD_JSON_FILE - - echo "{" >> "$SCRIPT_DIR/$UPLOAD_JSON_FILE" - echo " \"name\":\"$(_get_package_name)\"," >> "$SCRIPT_DIR/$UPLOAD_JSON_FILE" - echo " \"version\":\"$(_get_package_version)\"," >> "$SCRIPT_DIR/$UPLOAD_JSON_FILE" - echo " \"repositoryId\":\"$REPO_ID\"," >> "$SCRIPT_DIR/$UPLOAD_JSON_FILE" - echo " \"sourceUrl\":\"$UPLOAD_URL\"" >> "$SCRIPT_DIR/$UPLOAD_JSON_FILE" - echo "}" >> "$SCRIPT_DIR/$UPLOAD_JSON_FILE" -} - -call_repo_client(){ - $SCRIPT_DIR/repoapi_client.sh -addpkg $SCRIPT_DIR/$UPLOAD_JSON_FILE -} - -# Extract the package name from the .deb filename -_get_package_name(){ - local deb_filename=$(basename $DEB_FILE) - local package_name=${deb_filename%%_*} - - echo $package_name -} - -# Extract the package version from the .deb filename -_get_package_version(){ - local deb_filename=$(basename $DEB_FILE) - local package_version=${deb_filename#*_} - package_version=${package_version%-*} - - echo $package_version -} - -execute diff --git a/tools/DebianPackageTool/test/integration_tests/test_package.bats b/tools/DebianPackageTool/test/integration_tests/test_package.bats index f0c0c90ef..27e02908b 100755 --- a/tools/DebianPackageTool/test/integration_tests/test_package.bats +++ b/tools/DebianPackageTool/test/integration_tests/test_package.bats @@ -47,6 +47,14 @@ download_and_install_last_version(){ install_last_version } +delete_last_version(){ + rm -f "$DIR/last_version.deb" +} + +cleanup(){ + delete_last_version +} + @test "package install + removal test" { install_package remove_package @@ -68,5 +76,6 @@ download_and_install_last_version(){ remove_package install_package purge_package + cleanup fi } From b99e40bfab48cb4849216b29a2bd1016a18a93a1 Mon Sep 17 00:00:00 2001 From: Sridhar Periyasamy Date: Tue, 8 Mar 2016 18:46:54 -0800 Subject: [PATCH 13/31] Address PR feedback and remove Azure CLI from dockerfiles We no longer need Azure CLI since publish is now via C#. --- packaging/osx/package-osx.sh | 8 ++++---- scripts/docker/centos/Dockerfile | 6 ------ scripts/docker/ubuntu/Dockerfile | 5 ----- 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/packaging/osx/package-osx.sh b/packaging/osx/package-osx.sh index e767bcedb..819a7e1f6 100755 --- a/packaging/osx/package-osx.sh +++ b/packaging/osx/package-osx.sh @@ -16,9 +16,9 @@ help(){ echo "Usage: $0 [--version ] [--input ] [--output ] [--help]" echo "" echo "Options:" - echo " --version Specify a version for the package." + echo " --version Specify a version for the package. Version format is 4 '.' separated numbers - ..." echo " --input Package the entire contents of the directory tree." - echo " --output The path to which the package will be written." + echo " --output The path to where the package will be written." exit 1 } @@ -56,11 +56,11 @@ if [ -z "$OUTPUT_PKG" ]; then fi if [ -z "$INPUT_DIR" ]; then - echo "Provide an inout directory. Missing option '--input'" && help + echo "Provide an input directory. Missing option '--input'" && help fi if [ ! -d "$INPUT_DIR" ]; then - echo "Missing input directory - $INPUT_DIR" 1>&2 + echo "'$INPUT_DIR' - is either missing or not a directory" 1>&2 exit 1 fi diff --git a/scripts/docker/centos/Dockerfile b/scripts/docker/centos/Dockerfile index c44a40a41..70aae5bde 100644 --- a/scripts/docker/centos/Dockerfile +++ b/scripts/docker/centos/Dockerfile @@ -24,12 +24,6 @@ RUN yum -q -y install tar git cmake clang make RUN update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++ 100 RUN update-alternatives --set c++ /usr/bin/clang++ -# Install azure cli. We need this to publish artifacts. -RUN yum -y install nodejs && \ - yum -y install npm && \ - npm install -g azure-cli - - RUN yum -q -y install sudo # Setup User to match Host User, and give superuser permissions diff --git a/scripts/docker/ubuntu/Dockerfile b/scripts/docker/ubuntu/Dockerfile index 852a81720..8fe1e751d 100644 --- a/scripts/docker/ubuntu/Dockerfile +++ b/scripts/docker/ubuntu/Dockerfile @@ -69,11 +69,6 @@ RUN apt-get -qq install -y debhelper build-essential devscripts git cmake RUN update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-3.5 100 RUN update-alternatives --set c++ /usr/bin/clang++-3.5 -# Install azure cli. We need this to publish artifacts. -RUN apt-get -qqy install nodejs-legacy && \ - apt-get -qqy install npm && \ - npm install -g azure-cli - # Setup User to match Host User, and give superuser permissions ARG USER_ID=0 RUN useradd -m code_executor -u ${USER_ID} -g sudo From 628f54c77cba64849bddbaec2bd1f0a46cd685b4 Mon Sep 17 00:00:00 2001 From: Troy Dai Date: Wed, 9 Mar 2016 08:15:18 -0800 Subject: [PATCH 14/31] Send an empty error message after global error is cleared --- .../Messengers/GlobalErrorMessenger.cs | 11 +++++++++++ test/dotnet-projectmodel-server.Tests/DthTests.cs | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/dotnet/commands/dotnet-projectmodel-server/Messengers/GlobalErrorMessenger.cs b/src/dotnet/commands/dotnet-projectmodel-server/Messengers/GlobalErrorMessenger.cs index 3efea3e1d..854465ef8 100644 --- a/src/dotnet/commands/dotnet-projectmodel-server/Messengers/GlobalErrorMessenger.cs +++ b/src/dotnet/commands/dotnet-projectmodel-server/Messengers/GlobalErrorMessenger.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; +using Microsoft.DotNet.ProjectModel.Server.Models; namespace Microsoft.DotNet.ProjectModel.Server.Messengers { @@ -22,6 +23,16 @@ namespace Microsoft.DotNet.ProjectModel.Server.Messengers { send(local.GlobalErrorMessage); } + else + { + send(new ErrorMessage + { + Message = null, + Path = null, + Line = -1, + Column = -1 + }); + } } protected override void SetValue(ProjectSnapshot local, ProjectSnapshot remote) diff --git a/test/dotnet-projectmodel-server.Tests/DthTests.cs b/test/dotnet-projectmodel-server.Tests/DthTests.cs index 86f018f1b..9a38ac4f8 100644 --- a/test/dotnet-projectmodel-server.Tests/DthTests.cs +++ b/test/dotnet-projectmodel-server.Tests/DthTests.cs @@ -358,8 +358,8 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests File.WriteAllText(projectFile, content); client.SendPayLoad(testProject, MessageTypes.FilesChanged); - messages = client.DrainAllMessages(); - messages.AssertDoesNotContain(MessageTypes.Error); + var clearError = client.DrainTillFirst(MessageTypes.Error); + clearError.Payload.AsJObject().AssertProperty("Message", null as string); } } } From 1737fa8cbc3ba355bdaf4fa5132b0aa5972cca6c Mon Sep 17 00:00:00 2001 From: Sridhar Periyasamy Date: Wed, 9 Mar 2016 02:51:58 +0000 Subject: [PATCH 15/31] Fix debian package tests --- packaging/debian/dotnet-debian_config.json | 2 +- packaging/debian/dotnet-nightly-debian_config.json | 2 +- scripts/package/package-debian.sh | 9 +++++---- .../test/integration_tests/test_package.bats | 3 +-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packaging/debian/dotnet-debian_config.json b/packaging/debian/dotnet-debian_config.json index 550508f8c..a3c4873a2 100644 --- a/packaging/debian/dotnet-debian_config.json +++ b/packaging/debian/dotnet-debian_config.json @@ -28,7 +28,7 @@ }, "debian_dependencies":{ - "libssl-dev" : {}, + "libssl1.0.0" : {}, "clang-3.5" : {}, "libcurl3" : {} }, diff --git a/packaging/debian/dotnet-nightly-debian_config.json b/packaging/debian/dotnet-nightly-debian_config.json index 49652c929..cc7d7e9ab 100644 --- a/packaging/debian/dotnet-nightly-debian_config.json +++ b/packaging/debian/dotnet-nightly-debian_config.json @@ -28,7 +28,7 @@ }, "debian_dependencies":{ - "libssl-dev" : {}, + "libssl1.0.0" : {}, "clang-3.5" : {}, "libcurl3" : {} }, diff --git a/scripts/package/package-debian.sh b/scripts/package/package-debian.sh index f8cbcc0e9..ab1d7e324 100755 --- a/scripts/package/package-debian.sh +++ b/scripts/package/package-debian.sh @@ -34,7 +34,6 @@ help(){ while [[ $# > 0 ]]; do lowerI="$(echo $1 | awk '{print tolower($0)}')" - echo "$lowerI" case $lowerI in -m|--manpages) MANPAGE_DIR=$2 @@ -64,7 +63,6 @@ while [[ $# > 0 ]]; do help ;; *) - echo $lowerI break ;; esac @@ -78,6 +76,9 @@ PACKAGE_OUTPUT_DIR=$(dirname "${OUTPUT_DEBIAN_FILE}") PACKAGE_LAYOUT_DIR="$PACKAGE_OUTPUT_DIR/deb_intermediate" TEST_STAGE_DIR="$PACKAGE_OUTPUT_DIR/debian_tests" +# remove any residual deb files from earlier builds +rm -f "$PACKAGE_OUTPUT_DIR/*.deb" + execute_build(){ create_empty_debian_layout copy_files_to_debian_layout @@ -165,8 +166,8 @@ run_e2e_test(){ execute_build -rm -f "$OUTPUT_DEBIAN_FILE" DEBIAN_FILE=$(find $PACKAGE_OUTPUT_DIR -iname "*.deb") -mv -f "$DEBIAN_FILE" "$OUTPUT_DEBIAN_FILE" execute_test + +mv -f "$DEBIAN_FILE" "$OUTPUT_DEBIAN_FILE" diff --git a/tools/DebianPackageTool/test/integration_tests/test_package.bats b/tools/DebianPackageTool/test/integration_tests/test_package.bats index 27e02908b..8f4c75053 100755 --- a/tools/DebianPackageTool/test/integration_tests/test_package.bats +++ b/tools/DebianPackageTool/test/integration_tests/test_package.bats @@ -51,7 +51,7 @@ delete_last_version(){ rm -f "$DIR/last_version.deb" } -cleanup(){ +teardown(){ delete_last_version } @@ -76,6 +76,5 @@ cleanup(){ remove_package install_package purge_package - cleanup fi } From 53dd5f4a235bbbb83cf3885776aef08ec817b314 Mon Sep 17 00:00:00 2001 From: Sridhar Periyasamy Date: Wed, 9 Mar 2016 20:15:06 +0000 Subject: [PATCH 16/31] Address more PR feedback - Add libssl-dev dependency to DockerFile, because the package upgrade test still depend on this. It can be removed once a newer package without libssl-dev dependency is uploaded. - Check pre-reqs in the package script. --- scripts/docker/ubuntu/Dockerfile | 1 + scripts/dotnet-cli-build/InstallerTargets.cs | 3 +- scripts/dotnet-cli-build/Utils/Monikers.cs | 1 - scripts/package/package-debian.sh | 53 ++++++++++++++++---- 4 files changed, 45 insertions(+), 13 deletions(-) diff --git a/scripts/docker/ubuntu/Dockerfile b/scripts/docker/ubuntu/Dockerfile index 8fe1e751d..c57e4e4ca 100644 --- a/scripts/docker/ubuntu/Dockerfile +++ b/scripts/docker/ubuntu/Dockerfile @@ -55,6 +55,7 @@ RUN echo "deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.6 main" | tee libsasl2-2 \ libsqlite3-0 \ libssl1.0.0 \ + libssl-dev \ libtasn1-6 \ libwind0-heimdal diff --git a/scripts/dotnet-cli-build/InstallerTargets.cs b/scripts/dotnet-cli-build/InstallerTargets.cs index 7f1fa1649..be1a4836a 100644 --- a/scripts/dotnet-cli-build/InstallerTargets.cs +++ b/scripts/dotnet-cli-build/InstallerTargets.cs @@ -45,9 +45,10 @@ namespace Microsoft.DotNet.Cli.Build var version = c.BuildContext.Get("BuildVersion").SimpleVersion; var debFile = c.BuildContext.Get("InstallerFile"); var manPagesDir = Path.Combine(Dirs.RepoRoot, "Documentation", "manpages"); + var previousVersionURL = $"https://dotnetcli.blob.core.windows.net/dotnet/{channel}/Installers/Latest/dotnet-ubuntu-x64.latest.deb"; Cmd(Path.Combine(Dirs.RepoRoot, "scripts", "package", "package-debian.sh"), - "-v", version, "-i", Dirs.Stage2, "-o", debFile, "-p", packageName, "-m", manPagesDir, "-c", channel) + "-v", version, "-i", Dirs.Stage2, "-o", debFile, "-p", packageName, "-m", manPagesDir, "--previous-version-url", previousVersionURL) .Execute() .EnsureSuccessful(); return c.Success(); diff --git a/scripts/dotnet-cli-build/Utils/Monikers.cs b/scripts/dotnet-cli-build/Utils/Monikers.cs index 522de0f05..ae8052636 100644 --- a/scripts/dotnet-cli-build/Utils/Monikers.cs +++ b/scripts/dotnet-cli-build/Utils/Monikers.cs @@ -33,7 +33,6 @@ namespace Microsoft.DotNet.Cli.Build break; default: throw new Exception($"Unknown channel - {channel}"); - break; } return packageName; diff --git a/scripts/package/package-debian.sh b/scripts/package/package-debian.sh index ab1d7e324..e06748739 100755 --- a/scripts/package/package-debian.sh +++ b/scripts/package/package-debian.sh @@ -25,16 +25,18 @@ help(){ echo "Options:" echo " --version Specify a version for the package." echo " --input Package the entire contents of the directory tree." - echo " --manpages Directory containing man pages for the package." + echo " --manpages Directory containing man pages for the package (Optional)." echo " --output The full path to which the package will be written." echo " --package-name Package to identify during installation. Example - 'dotnet-nightly', 'dotnet'" - echo " --channel Channel against which to run the upgrade tests. Example - 'dev', 'beta'" + echo " --previous-version-url Url to the previous version of the debian packge against which to run the upgrade tests." exit 1 } -while [[ $# > 0 ]]; do - lowerI="$(echo $1 | awk '{print tolower($0)}')" - case $lowerI in +parseargs(){ + + while [[ $# > 0 ]]; do + lowerI="$(echo $1 | awk '{print tolower($0)}')" + case $lowerI in -m|--manpages) MANPAGE_DIR=$2 shift @@ -55,8 +57,8 @@ while [[ $# > 0 ]]; do DOTNET_CLI_VERSION=$2 shift ;; - -c|--channel) - CHANNEL=$2 + --previous-version-url) + PREVIOUS_VERSION_URL=$2 shift ;; --help) @@ -65,9 +67,38 @@ while [[ $# > 0 ]]; do *) break ;; - esac - shift -done + esac + shift + done + + if [ -z "$DOTNET_CLI_VERSION" ]; then + echo "Provide a version number. Missing option '--version'" && help + fi + + if [ -z "$OUTPUT_DEBIAN_FILE" ]; then + echo "Provide an output deb. Missing option '--output'" && help + fi + + if [ -z "$REPO_BINARIES_DIR" ]; then + echo "Provide an input directory. Missing option '--input'" && help + fi + + if [ -z "$DOTNET_DEB_PACKAGE_NAME" ]; then + echo "Provide an the name for the debian package. Missing option '--package-name'" && help + fi + + if [ -z "$PREVIOUS_VERSION_URL" ]; then + echo "Provide a URL to the previous debian pacakge (Required for running upgrade tests). Missing option '--previous-version-url'" && help + fi + + if [ ! -d "$REPO_BINARIES_DIR" ]; then + echo "'$REPO_BINARIES_DIR' - is either missing or not a directory" 1>&2 + exit 1 + fi + +} + +parseargs $@ PACKAGING_ROOT="$REPOROOT/packaging/debian" PACKAGING_TOOL_DIR="$REPOROOT/tools/DebianPackageTool" @@ -148,7 +179,7 @@ remove_debian_package() { run_package_integrity_tests() { # Set LAST_VERSION_URL to enable upgrade tests - export LAST_VERSION_URL="https://dotnetcli.blob.core.windows.net/dotnet/$CHANNEL/Installers/Latest/dotnet-ubuntu-x64.latest.deb" + export LAST_VERSION_URL="$PREVIOUS_VERSION_URL" $TEST_STAGE_DIR/bin/bats $PACKAGE_OUTPUT_DIR/test_package.bats } From 9631ba8927fcf305183dc656c26668fe2817d334 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Tue, 8 Mar 2016 16:46:50 -0800 Subject: [PATCH 17/31] Generate actual deps.json file --- .../Executable.cs | 67 +++++++++++++++++-- .../LibraryExporterExtensions.cs | 36 +--------- .../ProjectContextExtensions.cs | 24 +++++++ .../Compilation/LibraryExportBuilder.cs | 2 - .../DependencyContextBuilder.cs | 8 ++- .../FileNameSuffixes.cs | 1 + .../Graph/LockFileReader.cs | 3 +- .../RuntimeOutputFiles.cs | 12 ++++ .../DependencyContext.cs | 17 +++-- .../DependencyContextWriter.cs | 20 +++++- .../RuntimeAssembly.cs | 15 ++++- .../commands/dotnet-build/CompileContext.cs | 4 +- .../commands/dotnet-compile/CompilerUtil.cs | 21 ------ .../dotnet-compile/ManagedCompiler.cs | 3 +- src/dotnet/commands/dotnet-restore/Program.cs | 2 +- .../DependencyContextBuilderTests.cs | 23 ++++++- .../RuntimeAssemblyTests.cs | 27 ++++++++ test/dotnet-build.Tests/BuildOutputTests.cs | 1 + test/dotnet-build.Tests/BuildPortableTests.cs | 1 + .../Microsoft.DotNet.Tools.Publish.Tests.cs | 2 + 20 files changed, 211 insertions(+), 78 deletions(-) create mode 100644 test/Microsoft.Extensions.DependencyModel.Tests/RuntimeAssemblyTests.cs diff --git a/src/Microsoft.DotNet.Compiler.Common/Executable.cs b/src/Microsoft.DotNet.Compiler.Common/Executable.cs index 3aedeedc8..03c89273c 100644 --- a/src/Microsoft.DotNet.Compiler.Common/Executable.cs +++ b/src/Microsoft.DotNet.Compiler.Common/Executable.cs @@ -12,6 +12,7 @@ using Microsoft.DotNet.Files; using Microsoft.DotNet.ProjectModel; using Microsoft.DotNet.ProjectModel.Compilation; using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.Extensions.DependencyModel; using NuGet.Frameworks; namespace Microsoft.Dotnet.Cli.Compiler.Common @@ -22,19 +23,22 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common private readonly LibraryExporter _exporter; + private readonly string _configuration; + private readonly OutputPaths _outputPaths; private readonly string _runtimeOutputPath; private readonly string _intermediateOutputPath; - public Executable(ProjectContext context, OutputPaths outputPaths, LibraryExporter exporter) + public Executable(ProjectContext context, OutputPaths outputPaths, LibraryExporter exporter, string configuration) { _context = context; _outputPaths = outputPaths; _runtimeOutputPath = outputPaths.RuntimeOutputPath; _intermediateOutputPath = outputPaths.IntermediateOutputDirectoryPath; _exporter = exporter; + _configuration = configuration; } public void MakeCompilationOutputRunnable() @@ -101,9 +105,7 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common private void WriteDepsFileAndCopyProjectDependencies(LibraryExporter exporter) { - exporter - .GetDependencies(LibraryType.Package) - .WriteDepsTo(Path.Combine(_runtimeOutputPath, _context.ProjectFile.Name + FileNameSuffixes.Deps)); + WriteDeps(exporter); var projectExports = exporter.GetDependencies(LibraryType.Project); CopyAssemblies(projectExports); @@ -113,6 +115,36 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common CopyAssets(packageExports); } + public void WriteDeps(LibraryExporter exporter) + { + var path = Path.Combine(_runtimeOutputPath, _context.ProjectFile.Name + FileNameSuffixes.Deps); + CreateDirectoryIfNotExists(path); + File.WriteAllLines(path, exporter + .GetDependencies(LibraryType.Package) + .SelectMany(GenerateLines)); + + var compilerOptions = _context.ResolveCompilationOptions(_configuration); + var includeCompile = compilerOptions.PreserveCompilationContext == true; + + var exports = exporter.GetAllExports().ToArray(); + var dependencyContext = new DependencyContextBuilder().Build( + compilerOptions: includeCompile? compilerOptions: null, + compilationExports: includeCompile ? exports : null, + runtimeExports: exports, + portable: string.IsNullOrEmpty(_context.RuntimeIdentifier), + target: _context.TargetFramework, + runtime: _context.RuntimeIdentifier ?? string.Empty); + + var writer = new DependencyContextWriter(); + var depsJsonFile = Path.Combine(_runtimeOutputPath, _context.ProjectFile.Name + FileNameSuffixes.DepsJson); + using (var fileStream = File.Create(depsJsonFile)) + { + writer.Write(dependencyContext, fileStream); + } + + } + + public void GenerateBindingRedirects(LibraryExporter exporter) { var outputName = _outputPaths.RuntimeFiles.Assembly; @@ -141,5 +173,32 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common appConfig.Save(stream); } } + + + private static void CreateDirectoryIfNotExists(string path) + { + var depsFile = new FileInfo(path); + depsFile.Directory.Create(); + } + + private static IEnumerable GenerateLines(LibraryExport export) + { + return GenerateLines(export, export.RuntimeAssemblies, "runtime") + .Union(GenerateLines(export, export.NativeLibraries, "native")); + } + + private static IEnumerable GenerateLines(LibraryExport export, IEnumerable items, string type) + { + return items.Select(i => DepsFormatter.EscapeRow(new[] + { + export.Library.Identity.Type.Value, + export.Library.Identity.Name, + export.Library.Identity.Version.ToNormalizedString(), + export.Library.Hash, + type, + i.Name, + i.RelativePath + })); + } } } diff --git a/src/Microsoft.DotNet.Compiler.Common/LibraryExporterExtensions.cs b/src/Microsoft.DotNet.Compiler.Common/LibraryExporterExtensions.cs index c4e088401..c6c340b1f 100644 --- a/src/Microsoft.DotNet.Compiler.Common/LibraryExporterExtensions.cs +++ b/src/Microsoft.DotNet.Compiler.Common/LibraryExporterExtensions.cs @@ -1,45 +1,15 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using Microsoft.DotNet.ProjectModel; using Microsoft.DotNet.ProjectModel.Compilation; +using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.Extensions.DependencyModel; namespace Microsoft.DotNet.Cli.Compiler.Common { public static class LibraryExporterExtensions { - public static void WriteDepsTo(this IEnumerable exports, string path) - { - CreateDirectoryIfNotExists(path); - - File.WriteAllLines(path, exports.SelectMany(GenerateLines)); - } - - private static void CreateDirectoryIfNotExists(string path) - { - var depsFile = new FileInfo(path); - depsFile.Directory.Create(); - } - - private static IEnumerable GenerateLines(LibraryExport export) - { - return GenerateLines(export, export.RuntimeAssemblies, "runtime") - .Union(GenerateLines(export, export.NativeLibraries, "native")); - } - - private static IEnumerable GenerateLines(LibraryExport export, IEnumerable items, string type) - { - return items.Select(i => DepsFormatter.EscapeRow(new[] - { - export.Library.Identity.Type.Value, - export.Library.Identity.Name, - export.Library.Identity.Version.ToNormalizedString(), - export.Library.Hash, - type, - i.Name, - i.RelativePath - })); - } - public static void CopyTo(this IEnumerable assets, string destinationPath) { if (!Directory.Exists(destinationPath)) diff --git a/src/Microsoft.DotNet.Compiler.Common/ProjectContextExtensions.cs b/src/Microsoft.DotNet.Compiler.Common/ProjectContextExtensions.cs index 9313f9b60..f0e94f8df 100644 --- a/src/Microsoft.DotNet.Compiler.Common/ProjectContextExtensions.cs +++ b/src/Microsoft.DotNet.Compiler.Common/ProjectContextExtensions.cs @@ -2,7 +2,9 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System; using System.Collections.Generic; +using System.IO; using System.Linq; using Microsoft.DotNet.ProjectModel; using NuGet.Frameworks; @@ -28,5 +30,27 @@ namespace Microsoft.DotNet.Cli.Compiler.Common return baseOption; } + + + // used in incremental compilation for the key file + public static CommonCompilerOptions ResolveCompilationOptions(this ProjectContext context, string configuration) + { + var compilationOptions = context.GetLanguageSpecificCompilerOptions(context.TargetFramework, configuration); + + // Path to strong naming key in environment variable overrides path in project.json + var environmentKeyFile = Environment.GetEnvironmentVariable(EnvironmentNames.StrongNameKeyFile); + + if (!string.IsNullOrWhiteSpace(environmentKeyFile)) + { + compilationOptions.KeyFile = environmentKeyFile; + } + else if (!string.IsNullOrWhiteSpace(compilationOptions.KeyFile)) + { + // Resolve full path to key file + compilationOptions.KeyFile = + Path.GetFullPath(Path.Combine(context.ProjectFile.ProjectDirectory, compilationOptions.KeyFile)); + } + return compilationOptions; + } } } diff --git a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExportBuilder.cs b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExportBuilder.cs index 3bf323893..5b764781b 100644 --- a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExportBuilder.cs +++ b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExportBuilder.cs @@ -16,8 +16,6 @@ namespace Microsoft.DotNet.ProjectModel.Compilation private IList _compilationAssets; - private IList _debugAssets; - private IList _sourceReferences; private IList _nativeLibraries; diff --git a/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs b/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs index b74a2a869..8b088e88c 100644 --- a/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs +++ b/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs @@ -29,6 +29,7 @@ namespace Microsoft.Extensions.DependencyModel public DependencyContext Build(CommonCompilerOptions compilerOptions, IEnumerable compilationExports, IEnumerable runtimeExports, + bool portable, NuGetFramework target, string runtime) { @@ -44,11 +45,14 @@ namespace Microsoft.Extensions.DependencyModel .Select(identity => new Dependency(identity.Name, identity.Version.ToString())) .ToDictionary(dependency => dependency.Name); + var compilationOptions = compilerOptions != null + ? GetCompilationOptions(compilerOptions) + : CompilationOptions.Default; return new DependencyContext( target.DotNetFrameworkName, runtime, - false, - GetCompilationOptions(compilerOptions), + portable, + compilationOptions, GetLibraries(compilationExports, dependencyLookup, runtime: false).Cast(), GetLibraries(runtimeExports, dependencyLookup, runtime: true).Cast(), new KeyValuePair[0]); diff --git a/src/Microsoft.DotNet.ProjectModel/FileNameSuffixes.cs b/src/Microsoft.DotNet.ProjectModel/FileNameSuffixes.cs index c09f5bf07..12bedfdb4 100644 --- a/src/Microsoft.DotNet.ProjectModel/FileNameSuffixes.cs +++ b/src/Microsoft.DotNet.ProjectModel/FileNameSuffixes.cs @@ -6,6 +6,7 @@ namespace Microsoft.DotNet.ProjectModel public static class FileNameSuffixes { public const string Deps = ".deps"; + public const string DepsJson = ".deps.json"; public static PlatformFileNameSuffixes CurrentPlatform { diff --git a/src/Microsoft.DotNet.ProjectModel/Graph/LockFileReader.cs b/src/Microsoft.DotNet.ProjectModel/Graph/LockFileReader.cs index dd5223aef..ad9bb0742 100644 --- a/src/Microsoft.DotNet.ProjectModel/Graph/LockFileReader.cs +++ b/src/Microsoft.DotNet.ProjectModel/Graph/LockFileReader.cs @@ -167,6 +167,7 @@ namespace Microsoft.DotNet.ProjectModel.Graph library.ResourceAssemblies = ReadObject(jobject.ValueAsJsonObject("resource"), ReadFileItem); library.NativeLibraries = ReadObject(jobject.ValueAsJsonObject("native"), ReadFileItem); library.ContentFiles = ReadObject(jobject.ValueAsJsonObject("contentFiles"), ReadContentFile); + library.RuntimeTargets = ReadObject(jobject.ValueAsJsonObject("runtimeTargets"), ReadRuntimeTarget); return library; } @@ -180,7 +181,7 @@ namespace Microsoft.DotNet.ProjectModel.Graph return new LockFileRuntimeTarget( path: property, - runtime: jsonObject.ValueAsString("runtime"), + runtime: jsonObject.ValueAsString("rid"), assetType: jsonObject.ValueAsString("assetType") ); } diff --git a/src/Microsoft.DotNet.ProjectModel/RuntimeOutputFiles.cs b/src/Microsoft.DotNet.ProjectModel/RuntimeOutputFiles.cs index 0659df5ad..7ade31bc1 100644 --- a/src/Microsoft.DotNet.ProjectModel/RuntimeOutputFiles.cs +++ b/src/Microsoft.DotNet.ProjectModel/RuntimeOutputFiles.cs @@ -39,6 +39,13 @@ namespace Microsoft.DotNet.ProjectModel return Path.ChangeExtension(Assembly, FileNameSuffixes.Deps); } } + public string DepsJson + { + get + { + return Path.ChangeExtension(Assembly, FileNameSuffixes.DepsJson); + } + } public string Config { @@ -61,6 +68,11 @@ namespace Microsoft.DotNet.ProjectModel { yield return Deps; } + + if (File.Exists(DepsJson)) + { + yield return DepsJson; + } } } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs index 229a090b9..c31ea8dc6 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs @@ -11,7 +11,7 @@ namespace Microsoft.Extensions.DependencyModel { public class DependencyContext { - private const string DepsResourceSufix = ".deps.json"; + private const string DepsJsonExtension = ".deps.json"; private const string DepsFileExtension = ".deps"; private static readonly Lazy _defaultContext = new Lazy(LoadDefault); @@ -32,10 +32,6 @@ namespace Microsoft.Extensions.DependencyModel { throw new ArgumentNullException(nameof(runtime)); } - if (compilationOptions == null) - { - throw new ArgumentNullException(nameof(compilationOptions)); - } if (compileLibraries == null) { throw new ArgumentNullException(nameof(compileLibraries)); @@ -87,7 +83,7 @@ namespace Microsoft.Extensions.DependencyModel throw new ArgumentNullException(nameof(assembly)); } - using (var stream = assembly.GetManifestResourceStream(assembly.GetName().Name + DepsResourceSufix)) + using (var stream = assembly.GetManifestResourceStream(assembly.GetName().Name + DepsJsonExtension)) { if (stream != null) { @@ -95,6 +91,15 @@ namespace Microsoft.Extensions.DependencyModel } } + var depsJsonFile = Path.ChangeExtension(assembly.Location, DepsJsonExtension); + if (File.Exists(depsJsonFile)) + { + using (var stream = File.OpenRead(depsJsonFile)) + { + return new DependencyContextJsonReader().Read(stream); + } + } + var depsFile = Path.ChangeExtension(assembly.Location, DepsFileExtension); if (File.Exists(depsFile)) { diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs index c5e0ca8ee..18dea9304 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs @@ -57,7 +57,7 @@ namespace Microsoft.Extensions.DependencyModel private JObject WriteCompilationOptions(CompilationOptions compilationOptions) { var o = new JObject(); - if (compilationOptions.Defines != null) + if (compilationOptions.Defines?.Any() == true) { o[DependencyContextStrings.DefinesPropertyName] = new JArray(compilationOptions.Defines); } @@ -73,7 +73,7 @@ namespace Microsoft.Extensions.DependencyModel AddPropertyIfNotNull(o, DependencyContextStrings.GenerateXmlDocumentationPropertyName, compilationOptions.GenerateXmlDocumentation); AddPropertyIfNotNull(o, DependencyContextStrings.DebugTypePropertyName, compilationOptions.DebugType); return o; - } + } private void AddPropertyIfNotNull(JObject o, string name, T value) { @@ -142,6 +142,10 @@ namespace Microsoft.Extensions.DependencyModel private void AddCompilationAssemblies(JObject libraryObject, IEnumerable compilationAssemblies) { + if (!compilationAssemblies.Any()) + { + return; + } libraryObject.Add(new JProperty(DependencyContextStrings.CompileTimeAssembliesKey, WriteAssemblies(compilationAssemblies)) ); @@ -149,6 +153,10 @@ namespace Microsoft.Extensions.DependencyModel private void AddRuntimeAssemblies(JObject libraryObject, IEnumerable runtimeAssemblies) { + if (!runtimeAssemblies.Any()) + { + return; + } libraryObject.Add(new JProperty(DependencyContextStrings.RuntimeAssembliesKey, WriteAssemblies(runtimeAssemblies.Select(a => a.Path))) ); @@ -156,6 +164,10 @@ namespace Microsoft.Extensions.DependencyModel private void AddDependencies(JObject libraryObject, IEnumerable dependencies) { + if (!dependencies.Any()) + { + return; + } libraryObject.Add( new JProperty(DependencyContextStrings.DependenciesPropertyName, new JObject( @@ -165,6 +177,10 @@ namespace Microsoft.Extensions.DependencyModel private void AddResourceAssemblies(JObject libraryObject, IEnumerable resourceAssemblies) { + if (!resourceAssemblies.Any()) + { + return; + } libraryObject.Add(DependencyContextStrings.ResourceAssembliesPropertyName, new JObject(resourceAssemblies.Select(a => new JProperty(a.Path, new JObject(new JProperty(DependencyContextStrings.LocalePropertyName, a.Locale)))) diff --git a/src/Microsoft.Extensions.DependencyModel/RuntimeAssembly.cs b/src/Microsoft.Extensions.DependencyModel/RuntimeAssembly.cs index dcbee3a14..4cfc002eb 100644 --- a/src/Microsoft.Extensions.DependencyModel/RuntimeAssembly.cs +++ b/src/Microsoft.Extensions.DependencyModel/RuntimeAssembly.cs @@ -1,6 +1,8 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System; +using System.Diagnostics; using System.IO; using System.Reflection; @@ -8,6 +10,7 @@ namespace Microsoft.Extensions.DependencyModel { public class RuntimeAssembly { + private const string NativeImageSufix = ".ni"; private readonly string _assemblyName; public RuntimeAssembly(string assemblyName, string path) @@ -22,7 +25,17 @@ namespace Microsoft.Extensions.DependencyModel public static RuntimeAssembly Create(string path) { - return new RuntimeAssembly(System.IO.Path.GetFileNameWithoutExtension(path), path); + var assemblyName = System.IO.Path.GetFileNameWithoutExtension(path); + if (assemblyName == null) + { + throw new ArgumentException($"Provided path has empty file name '{path}'", nameof(path)); + } + + if (assemblyName.EndsWith(NativeImageSufix)) + { + assemblyName = assemblyName.Substring(0, assemblyName.Length - NativeImageSufix.Length); + } + return new RuntimeAssembly(assemblyName, path); } } } \ No newline at end of file diff --git a/src/dotnet/commands/dotnet-build/CompileContext.cs b/src/dotnet/commands/dotnet-build/CompileContext.cs index de2b43475..237fb744c 100644 --- a/src/dotnet/commands/dotnet-build/CompileContext.cs +++ b/src/dotnet/commands/dotnet-build/CompileContext.cs @@ -436,7 +436,7 @@ namespace Microsoft.DotNet.Tools.Build CopyCompilationOutput(outputPaths); } - var executable = new Executable(runtimeContext, outputPaths, libraryExporter); + var executable = new Executable(runtimeContext, outputPaths, libraryExporter, _args.ConfigValue); executable.MakeCompilationOutputRunnable(); PatchMscorlibNextToCoreClr(runtimeContext, _args.ConfigValue); @@ -579,7 +579,7 @@ namespace Microsoft.DotNet.Tools.Build private static void AddCompilationOptions(ProjectContext project, string config, CompilerIO compilerIO) { - var compilerOptions = CompilerUtil.ResolveCompilationOptions(project, config); + var compilerOptions = project.ResolveCompilationOptions(config); // input: key file if (compilerOptions.KeyFile != null) diff --git a/src/dotnet/commands/dotnet-compile/CompilerUtil.cs b/src/dotnet/commands/dotnet-compile/CompilerUtil.cs index dda381ee7..739e46dfe 100644 --- a/src/dotnet/commands/dotnet-compile/CompilerUtil.cs +++ b/src/dotnet/commands/dotnet-compile/CompilerUtil.cs @@ -119,27 +119,6 @@ namespace Microsoft.DotNet.Tools.Compiler // used in incremental compilation public static IEnumerable GetCompilationSources(ProjectContext project) => project.ProjectFile.Files.SourceFiles; - // used in incremental compilation for the key file - public static CommonCompilerOptions ResolveCompilationOptions(ProjectContext context, string configuration) - { - var compilationOptions = context.GetLanguageSpecificCompilerOptions(context.TargetFramework, configuration); - - // Path to strong naming key in environment variable overrides path in project.json - var environmentKeyFile = Environment.GetEnvironmentVariable(EnvironmentNames.StrongNameKeyFile); - - if (!string.IsNullOrWhiteSpace(environmentKeyFile)) - { - compilationOptions.KeyFile = environmentKeyFile; - } - else if (!string.IsNullOrWhiteSpace(compilationOptions.KeyFile)) - { - // Resolve full path to key file - compilationOptions.KeyFile = - Path.GetFullPath(Path.Combine(context.ProjectFile.ProjectDirectory, compilationOptions.KeyFile)); - } - return compilationOptions; - } - //used in incremental precondition checks public static IEnumerable GetCommandsInvokedByCompile(ProjectContext project) { diff --git a/src/dotnet/commands/dotnet-compile/ManagedCompiler.cs b/src/dotnet/commands/dotnet-compile/ManagedCompiler.cs index d2b149b31..10944cc23 100644 --- a/src/dotnet/commands/dotnet-compile/ManagedCompiler.cs +++ b/src/dotnet/commands/dotnet-compile/ManagedCompiler.cs @@ -76,7 +76,7 @@ namespace Microsoft.DotNet.Tools.Compiler $"--out:{outputName}" }; - var compilationOptions = CompilerUtil.ResolveCompilationOptions(context, args.ConfigValue); + var compilationOptions = context.ResolveCompilationOptions(args.ConfigValue); var languageId = CompilerUtil.ResolveLanguageId(context); var references = new List(); @@ -114,6 +114,7 @@ namespace Microsoft.DotNet.Tools.Compiler var dependencyContext = new DependencyContextBuilder().Build(compilationOptions, allExports, allExports, + string.IsNullOrEmpty(context.RuntimeIdentifier), context.TargetFramework, context.RuntimeIdentifier ?? string.Empty); diff --git a/src/dotnet/commands/dotnet-restore/Program.cs b/src/dotnet/commands/dotnet-restore/Program.cs index a42330263..1b530edb0 100644 --- a/src/dotnet/commands/dotnet-restore/Program.cs +++ b/src/dotnet/commands/dotnet-restore/Program.cs @@ -163,7 +163,7 @@ namespace Microsoft.DotNet.Tools.Restore toolDescription.Identity.Name + FileNameSuffixes.Deps); var calculator = context.GetOutputPaths(Constants.DefaultConfiguration, buidBasePath: null, outputPath: context.ProjectDirectory); - var executable = new Executable(context, calculator, context.CreateExporter(Constants.DefaultConfiguration)); + var executable = new Executable(context, calculator, context.CreateExporter(Constants.DefaultConfiguration), null); executable.MakeCompilationOutputRunnable(); diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs index fd0cc08ae..c54e2f2b0 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs @@ -24,14 +24,16 @@ namespace Microsoft.Extensions.DependencyModel.Tests public DependencyContext Build(CommonCompilerOptions compilerOptions = null, IEnumerable compilationExports = null, IEnumerable runtimeExports = null, + bool portable = false, NuGetFramework target = null, string runtime = null) { _defaultFramework = NuGetFramework.Parse("net451"); return new DependencyContextBuilder(_referenceAssembliesPath).Build( - compilerOptions ?? new CommonCompilerOptions(), + compilerOptions, compilationExports ?? new LibraryExport[] { }, runtimeExports ?? new LibraryExport[] {}, + portable, target ?? _defaultFramework, runtime ?? string.Empty); } @@ -42,7 +44,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests var context = Build(new CommonCompilerOptions() { AllowUnsafe = true, - Defines = new[] {"Define", "D"}, + Defines = new[] { "Define", "D" }, DelaySign = true, EmitEntryPoint = true, GenerateXmlDocumentation = true, @@ -68,6 +70,23 @@ namespace Microsoft.Extensions.DependencyModel.Tests context.CompilationOptions.Platform.Should().Be("Platform"); } + + [Fact] + public void AlowsNullCompilationOptions() + { + var context = Build(compilerOptions: null); + + context.CompilationOptions.Should().Be(CompilationOptions.Default); + } + + [Fact] + public void SetsPortableFlag() + { + var context = Build(portable: true); + + context.IsPortable.Should().BeTrue(); + } + [Fact] public void FillsRuntimeAndTarget() { diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/RuntimeAssemblyTests.cs b/test/Microsoft.Extensions.DependencyModel.Tests/RuntimeAssemblyTests.cs new file mode 100644 index 000000000..a4a251381 --- /dev/null +++ b/test/Microsoft.Extensions.DependencyModel.Tests/RuntimeAssemblyTests.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using FluentAssertions; +using Xunit; + +namespace Microsoft.Extensions.DependencyModel.Tests +{ + public class RuntimeAssemblyTests + { + [Fact] + public void UsesFileNameAsAssemblyNameInCreate() + { + var assembly = RuntimeAssembly.Create("path/to/System.Collections.dll"); + assembly.Name.Name.Should().Be("System.Collections"); + } + + [Fact] + public void TrimsDotNiFromDllNames() + { + var assembly = RuntimeAssembly.Create("path/to/System.Collections.ni.dll"); + assembly.Name.Name.Should().Be("System.Collections"); + } + } +} diff --git a/test/dotnet-build.Tests/BuildOutputTests.cs b/test/dotnet-build.Tests/BuildOutputTests.cs index 7575875ef..8d8072456 100644 --- a/test/dotnet-build.Tests/BuildOutputTests.cs +++ b/test/dotnet-build.Tests/BuildOutputTests.cs @@ -27,6 +27,7 @@ namespace Microsoft.DotNet.Tools.Builder.Tests "TestApp" + FileNameSuffixes.DotNet.ProgramDatabase, "TestApp" + FileNameSuffixes.CurrentPlatform.Exe, "TestApp" + FileNameSuffixes.Deps, + "TestApp" + FileNameSuffixes.DepsJson, "TestLibrary" + FileNameSuffixes.DotNet.DynamicLib, "TestLibrary" + FileNameSuffixes.DotNet.ProgramDatabase }; diff --git a/test/dotnet-build.Tests/BuildPortableTests.cs b/test/dotnet-build.Tests/BuildPortableTests.cs index 83e1e8544..c9a0eebbd 100644 --- a/test/dotnet-build.Tests/BuildPortableTests.cs +++ b/test/dotnet-build.Tests/BuildPortableTests.cs @@ -28,6 +28,7 @@ namespace Microsoft.DotNet.Tools.Builder.Tests .HaveFiles(new[] { "BuildTestPortableProject.deps", + "BuildTestPortableProject.deps.json", "BuildTestPortableProject.dll", "BuildTestPortableProject.pdb" }); diff --git a/test/dotnet-publish.Tests/Microsoft.DotNet.Tools.Publish.Tests.cs b/test/dotnet-publish.Tests/Microsoft.DotNet.Tools.Publish.Tests.cs index 22562e818..853073aef 100644 --- a/test/dotnet-publish.Tests/Microsoft.DotNet.Tools.Publish.Tests.cs +++ b/test/dotnet-publish.Tests/Microsoft.DotNet.Tools.Publish.Tests.cs @@ -126,6 +126,7 @@ namespace Microsoft.DotNet.Tools.Publish.Tests publishCommand.GetOutputDirectory().Should().HaveFile("TestLibraryLesser.pdb"); publishCommand.GetOutputDirectory().Should().HaveFile("TestLibraryLesser.dll.config"); publishCommand.GetOutputDirectory().Should().NotHaveFile("TestLibraryLesser.deps"); + publishCommand.GetOutputDirectory().Should().NotHaveFile("TestLibraryLesser.deps.json"); // dependencies should also be copied publishCommand.GetOutputDirectory().Should().HaveFile("Newtonsoft.Json.dll"); @@ -138,6 +139,7 @@ namespace Microsoft.DotNet.Tools.Publish.Tests publishCommand.GetOutputDirectory().Should().HaveFile("TestLibraryLesser.pdb"); publishCommand.GetOutputDirectory().Should().NotHaveFile("TestLibraryLesser.dll.config"); publishCommand.GetOutputDirectory().Should().HaveFile("TestLibraryLesser.deps"); + publishCommand.GetOutputDirectory().Should().HaveFile("TestLibraryLesser.deps.json"); // dependencies should also be copied publishCommand.GetOutputDirectory().Should().HaveFile("Newtonsoft.Json.dll"); From c33c2ff12719ec03d407970884f687b825c38164 Mon Sep 17 00:00:00 2001 From: Sridhar Periyasamy Date: Wed, 9 Mar 2016 14:21:02 -0800 Subject: [PATCH 18/31] Fix build breaks for RHEL and Windows x86. --- .../TestProjects/BuildTestStandaloneProject/project.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/TestAssets/TestProjects/BuildTestStandaloneProject/project.json b/TestAssets/TestProjects/BuildTestStandaloneProject/project.json index d8b5d9d86..440d05828 100644 --- a/TestAssets/TestProjects/BuildTestStandaloneProject/project.json +++ b/TestAssets/TestProjects/BuildTestStandaloneProject/project.json @@ -13,8 +13,10 @@ }, "runtimes": { "win7-x64": {}, + "win7-x86": {}, "osx.10.10-x64": {}, "ubuntu.14.04-x64": {}, - "centos.7-x64": {} + "centos.7-x64": {}, + "rhel.7.2-x64": {} } } From ee4bbb43ffd289228ed7c05aa37b29c1551c99fd Mon Sep 17 00:00:00 2001 From: Jeremy Meng Date: Thu, 3 Mar 2016 18:38:58 +0000 Subject: [PATCH 19/31] Add support for building dotnet CLI on Debian. --- .../BuildTestStandaloneProject/project.json | 3 ++- .../CurrentPlatform.cs | 15 +++++++++++++- .../Enumerations/BuildPlatform.cs | 3 ++- scripts/dotnet-cli-build/CompileTargets.cs | 6 +++++- scripts/obtain/install.sh | 20 ++++++++++++++----- test/EndToEnd/EndToEndTest.cs | 14 ++++++++----- 6 files changed, 47 insertions(+), 14 deletions(-) diff --git a/TestAssets/TestProjects/BuildTestStandaloneProject/project.json b/TestAssets/TestProjects/BuildTestStandaloneProject/project.json index 440d05828..8d366cf72 100644 --- a/TestAssets/TestProjects/BuildTestStandaloneProject/project.json +++ b/TestAssets/TestProjects/BuildTestStandaloneProject/project.json @@ -17,6 +17,7 @@ "osx.10.10-x64": {}, "ubuntu.14.04-x64": {}, "centos.7-x64": {}, - "rhel.7.2-x64": {} + "rhel.7.2-x64": {}, + "debian.8.2-x64": {} } } diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/CurrentPlatform.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/CurrentPlatform.cs index c860436e7..d1e0a515f 100644 --- a/scripts/Microsoft.DotNet.Cli.Build.Framework/CurrentPlatform.cs +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/CurrentPlatform.cs @@ -65,11 +65,20 @@ namespace Microsoft.DotNet.Cli.Build.Framework } } + public static bool IsDebian + { + get + { + var osname = PlatformServices.Default.Runtime.OperatingSystem; + return string.Equals(osname, "debian", StringComparison.OrdinalIgnoreCase); + } + } + public static bool IsLinux { get { - return IsUbuntu || IsCentOS || IsRHEL; + return IsUbuntu || IsCentOS || IsRHEL || IsDebian; } } @@ -118,6 +127,10 @@ namespace Microsoft.DotNet.Cli.Build.Framework { return BuildPlatform.RHEL; } + else if (IsDebian) + { + return BuildPlatform.Debian; + } else { return default(BuildPlatform); diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/Enumerations/BuildPlatform.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/Enumerations/BuildPlatform.cs index adb2c83d6..46578d3ca 100644 --- a/scripts/Microsoft.DotNet.Cli.Build.Framework/Enumerations/BuildPlatform.cs +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/Enumerations/BuildPlatform.cs @@ -8,6 +8,7 @@ namespace Microsoft.DotNet.Cli.Build.Framework OSX = 4, Ubuntu = 5, CentOS = 6, - RHEL = 7 + RHEL = 7, + Debian = 8 } } diff --git a/scripts/dotnet-cli-build/CompileTargets.cs b/scripts/dotnet-cli-build/CompileTargets.cs index bbf03cf4f..1fc300ce0 100644 --- a/scripts/dotnet-cli-build/CompileTargets.cs +++ b/scripts/dotnet-cli-build/CompileTargets.cs @@ -260,7 +260,7 @@ namespace Microsoft.DotNet.Cli.Build { packageId = "toolchain.ubuntu.14.04-x64.Microsoft.DotNet.AppDep"; } - else if (CurrentPlatform.IsCentOS || CurrentPlatform.IsRHEL) + else if (CurrentPlatform.IsCentOS || CurrentPlatform.IsRHEL || CurrentPlatform.IsDebian) { c.Warn($"Native compilation is not yet working on {CurrentPlatform.Current}"); return c.Success(); @@ -308,6 +308,10 @@ namespace Microsoft.DotNet.Cli.Build // CentOS runtime is in the runtime.rhel.7-x64... package. packageId = "runtime.rhel.7-x64.Microsoft.NETCore.Runtime.CoreCLR"; } + else if (CurrentPlatform.IsDebian) + { + packageId = "runtime.debian.8.2-x64.Microsoft.NETCore.Runtime.CoreCLR"; + } else if (CurrentPlatform.IsOSX) { packageId = "runtime.osx.10.10-x64.Microsoft.NETCore.Runtime.CoreCLR"; diff --git a/scripts/obtain/install.sh b/scripts/obtain/install.sh index 362e7a57c..c212eae44 100755 --- a/scripts/obtain/install.sh +++ b/scripts/obtain/install.sh @@ -85,6 +85,8 @@ current_os() echo "centos" elif [ "$(cat /etc/*-release | grep -cim1 rhel)" -eq 1 ]; then echo "rhel.7" + elif [ "$(cat /etc/*-release | grep -cim1 debian)" -eq 1 ]; then + echo "debian" fi fi } @@ -106,11 +108,19 @@ check_pre_reqs() { fi if [ "$(uname)" = "Linux" ]; then - [ -z "$(ldconfig -p | grep libunwind)" ] && say_err "Unable to locate libunwind. Install libunwind to continue" && _failing=true - [ -z "$(ldconfig -p | grep libssl)" ] && say_err "Unable to locate libssl. Install libssl to continue" && _failing=true - [ -z "$(ldconfig -p | grep libcurl)" ] && say_err "Unable to locate libcurl. Install libcurl to continue" && _failing=true - [ -z "$(ldconfig -p | grep libicu)" ] && say_err "Unable to locate libicu. Install libicu to continue" && _failing=true - [ -z "$(ldconfig -p | grep gettext)" ] && say_err "Unable to locate gettext. Install gettext to continue" && _failing=true + + if ! [ -x "$(command -v ldconfig)" ]; then + echo "ldconfig is not in PATH, trying /sbin/ldconfig." + LDCONFIG_COMMAND="/sbin/ldconfig" + else + LDCONFIG_COMMAND="ldconfig" + fi + + [ -z "$($LDCONFIG_COMMAND -p | grep libunwind)" ] && say_err "Unable to locate libunwind. Install libunwind to continue" && _failing=true + [ -z "$($LDCONFIG_COMMAND -p | grep libssl)" ] && say_err "Unable to locate libssl. Install libssl to continue" && _failing=true + [ -z "$($LDCONFIG_COMMAND -p | grep libcurl)" ] && say_err "Unable to locate libcurl. Install libcurl to continue" && _failing=true + [ -z "$($LDCONFIG_COMMAND -p | grep libicu)" ] && say_err "Unable to locate libicu. Install libicu to continue" && _failing=true + [ -z "$($LDCONFIG_COMMAND -p | grep gettext)" ] && say_err "Unable to locate gettext. Install gettext to continue" && _failing=true fi if [ "$_failing" = true ]; then diff --git a/test/EndToEnd/EndToEndTest.cs b/test/EndToEnd/EndToEndTest.cs index 5fb8edccc..be21d46ca 100644 --- a/test/EndToEnd/EndToEndTest.cs +++ b/test/EndToEnd/EndToEndTest.cs @@ -83,7 +83,7 @@ namespace Microsoft.DotNet.Tests.EndToEnd [Fact] public void TestDotnetBuildNativeRyuJit() { - if(!IsNativeCompilationSupported()) + if (!IsNativeCompilationSupported()) { return; } @@ -98,8 +98,8 @@ namespace Microsoft.DotNet.Tests.EndToEnd [Fact] public void TestDotnetBuildNativeCpp() { - if(!IsNativeCompilationSupported()) - { + if (!IsNativeCompilationSupported()) + { return; } @@ -113,8 +113,8 @@ namespace Microsoft.DotNet.Tests.EndToEnd [Fact] public void TestDotnetCompileNativeCppIncremental() { - if(!IsNativeCompilationSupported()) - { + if (!IsNativeCompilationSupported()) + { return; } @@ -226,6 +226,10 @@ namespace Microsoft.DotNet.Tests.EndToEnd Console.WriteLine("Skipping native compilation tests on CentOS/RHEL - https://github.com/dotnet/cli/issues/453"); isSupported = false; break; + case "debian": + Console.WriteLine("Skipping native compilation tests on Debian - https://github.com/dotnet/cli/issues/1666"); + isSupported = false; + break; case "windows": Console.WriteLine("Skipping native compilation tests on Windows x86 - https://github.com/dotnet/cli/issues/1550"); isSupported = RuntimeInformation.ProcessArchitecture != Architecture.X86; From 33ae98b48cb508ce71f9fd166283b3a6c0a1420c Mon Sep 17 00:00:00 2001 From: Jeremy Meng Date: Wed, 9 Mar 2016 23:35:21 +0000 Subject: [PATCH 20/31] Address CR feedback. Add Debian to IsPlatform() method. --- scripts/Microsoft.DotNet.Cli.Build.Framework/CurrentPlatform.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/CurrentPlatform.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/CurrentPlatform.cs index d1e0a515f..7e7ab0300 100644 --- a/scripts/Microsoft.DotNet.Cli.Build.Framework/CurrentPlatform.cs +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/CurrentPlatform.cs @@ -96,6 +96,8 @@ namespace Microsoft.DotNet.Cli.Build.Framework return IsCentOS; case BuildPlatform.RHEL: return IsRHEL; + case BuildPlatform.Debian: + return IsDebian; case BuildPlatform.Unix: return IsUnix; case BuildPlatform.Linux: From 56b1b829cfce8f585a00d0e575325d2f53b30be7 Mon Sep 17 00:00:00 2001 From: Sridhar Periyasamy Date: Wed, 9 Mar 2016 15:51:57 -0800 Subject: [PATCH 21/31] Fix centos build break when building using Docker `glibc-devel` to enable corehost compliation. --- scripts/docker/centos/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/docker/centos/Dockerfile b/scripts/docker/centos/Dockerfile index 70aae5bde..72162735d 100644 --- a/scripts/docker/centos/Dockerfile +++ b/scripts/docker/centos/Dockerfile @@ -18,7 +18,7 @@ RUN yum -q -y install unzip libunwind gettext libcurl-devel openssl-devel zlib l # apt-get -qqy install unzip curl libicu-dev libunwind8 gettext libssl-dev libcurl3-gnutls zlib1g liblttng-ust-dev lldb-3.6-dev lldb-3.6 # Install Build Prereqs -RUN yum -q -y install tar git cmake clang make +RUN yum -q -y install tar git cmake clang make glibc-devel # Use clang as c++ compiler RUN update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++ 100 From e1be00ecb3864dc541e5e222f462ce002234fd47 Mon Sep 17 00:00:00 2001 From: Andrew Stanton-Nurse Date: Wed, 9 Mar 2016 09:39:17 -0800 Subject: [PATCH 22/31] take NuGet with OSX fix --- src/Microsoft.DotNet.ProjectModel/project.json | 2 +- src/dotnet/project.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.DotNet.ProjectModel/project.json b/src/Microsoft.DotNet.ProjectModel/project.json index 82b9ecbe2..9479b166a 100644 --- a/src/Microsoft.DotNet.ProjectModel/project.json +++ b/src/Microsoft.DotNet.ProjectModel/project.json @@ -6,7 +6,7 @@ "description": "Types to model a .NET Project", "dependencies": { "System.Reflection.Metadata": "1.2.0-rc2-23901", - "NuGet.Packaging": "3.4.0-rtm-0724", + "NuGet.Packaging": "3.4.0-rtm-0733", "Microsoft.Extensions.FileSystemGlobbing": "1.0.0-rc2-15996", "Microsoft.Extensions.JsonParser.Sources": { "type": "build", diff --git a/src/dotnet/project.json b/src/dotnet/project.json index dcc0b0182..b4a5354f1 100644 --- a/src/dotnet/project.json +++ b/src/dotnet/project.json @@ -24,7 +24,7 @@ "Microsoft.CodeAnalysis.CSharp": "1.3.0-beta1-20160225-02", "Microsoft.DiaSymReader.Native": "1.3.3", - "NuGet.CommandLine.XPlat": "3.4.0-rtm-0724", + "NuGet.CommandLine.XPlat": "3.4.0-rtm-0733", "System.CommandLine": "0.1.0-e160119-1", "Microsoft.DotNet.ProjectModel": "1.0.0-*", From 02b2c75f5022b2f6bcc2b50cb8f2fac8842ec55d Mon Sep 17 00:00:00 2001 From: Sridhar Periyasamy Date: Wed, 9 Mar 2016 17:14:53 -0800 Subject: [PATCH 23/31] Fix to publish artifacts when running inside docker. --- scripts/dockerrun.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/dockerrun.sh b/scripts/dockerrun.sh index 2a4902893..0a3b3709f 100755 --- a/scripts/dockerrun.sh +++ b/scripts/dockerrun.sh @@ -94,9 +94,6 @@ echo "Using code from: $DOCKER_HOST_SHARE_DIR" docker run $INTERACTIVE -t --rm --sig-proxy=true \ --name $DOTNET_BUILD_CONTAINER_NAME \ -v $DOCKER_HOST_SHARE_DIR:/opt/code \ - -e SASTOKEN \ - -e STORAGE_ACCOUNT \ - -e STORAGE_CONTAINER \ -e CHANNEL \ -e CONNECTION_STRING \ -e REPO_ID \ @@ -104,5 +101,6 @@ docker run $INTERACTIVE -t --rm --sig-proxy=true \ -e REPO_PASS \ -e REPO_SERVER \ -e DOTNET_BUILD_SKIP_CROSSGEN \ + -e PUBLISH_TO_AZURE_BLOB \ $DOTNET_BUILD_CONTAINER_TAG \ $BUILD_COMMAND "$@" From c85cf24677aa6cefb15c26586790e1d72aa226d4 Mon Sep 17 00:00:00 2001 From: Sridhar Periyasamy Date: Wed, 9 Mar 2016 17:28:22 -0800 Subject: [PATCH 24/31] Fix docker build breaks in centos. --- scripts/docker/centos/Dockerfile | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/scripts/docker/centos/Dockerfile b/scripts/docker/centos/Dockerfile index 72162735d..ae3e87d6a 100644 --- a/scripts/docker/centos/Dockerfile +++ b/scripts/docker/centos/Dockerfile @@ -18,7 +18,18 @@ RUN yum -q -y install unzip libunwind gettext libcurl-devel openssl-devel zlib l # apt-get -qqy install unzip curl libicu-dev libunwind8 gettext libssl-dev libcurl3-gnutls zlib1g liblttng-ust-dev lldb-3.6-dev lldb-3.6 # Install Build Prereqs -RUN yum -q -y install tar git cmake clang make glibc-devel +# CMake 3.3.2 from GhettoForge; LLVM 3.6.2 built from source ourselves; +RUN yum install -y http://mirror.symnds.com/distributions/gf/el/7/plus/x86_64/cmake-3.3.2-1.gf.el7.x86_64.rpm \ + https://matell.blob.core.windows.net/rpms/clang-3.6.2-1.el7.centos.x86_64.rpm \ + https://matell.blob.core.windows.net/rpms/clang-libs-3.6.2-1.el7.centos.x86_64.rpm \ + https://matell.blob.core.windows.net/rpms/lldb-3.6.2-1.el7.centos.x86_64.rpm \ + https://matell.blob.core.windows.net/rpms/lldb-devel-3.6.2-1.el7.centos.x86_64.rpm \ + https://matell.blob.core.windows.net/rpms/llvm-3.6.2-1.el7.centos.x86_64.rpm \ + https://matell.blob.core.windows.net/rpms/llvm-libs-3.6.2-1.el7.centos.x86_64.rpm \ + which \ + make + +RUN yum -q -y install tar git # Use clang as c++ compiler RUN update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++ 100 From 0dad10253b44076f12c7086d85432ca6c4b1e308 Mon Sep 17 00:00:00 2001 From: Sridhar Periyasamy Date: Thu, 10 Mar 2016 10:23:52 -0800 Subject: [PATCH 25/31] Set the correct content type for version badges in blob storage. This is needed to display the version badges as images in external websites like github. --- scripts/dotnet-cli-build/PublishTargets.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/scripts/dotnet-cli-build/PublishTargets.cs b/scripts/dotnet-cli-build/PublishTargets.cs index 6a69fcd89..8c1324c20 100644 --- a/scripts/dotnet-cli-build/PublishTargets.cs +++ b/scripts/dotnet-cli-build/PublishTargets.cs @@ -154,9 +154,12 @@ namespace Microsoft.DotNet.Cli.Build private static void PublishFileAzure(string blob, string file) { CloudBlockBlob blockBlob = BlobContainer.GetBlockBlobReference(blob); - using (var fileStream = File.OpenRead(file)) + blockBlob.UploadFromFileAsync(file, FileMode.Open).Wait(); + + if (Path.GetExtension(blockBlob.Uri.AbsolutePath.ToLower()) == ".svg") { - blockBlob.UploadFromStreamAsync(fileStream).Wait(); + blockBlob.Properties.ContentType = "image/svg+xml"; + blockBlob.SetPropertiesAsync().Wait(); } } } From dceefd05c310886756286e4386999be924c5f8a4 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Thu, 10 Mar 2016 11:33:39 -0800 Subject: [PATCH 26/31] Fix issue preventing MVC gate to take a new dotnet cli --- src/dotnet/commands/dotnet-compile/ManagedCompiler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dotnet/commands/dotnet-compile/ManagedCompiler.cs b/src/dotnet/commands/dotnet-compile/ManagedCompiler.cs index 10944cc23..d4f3dc4c3 100644 --- a/src/dotnet/commands/dotnet-compile/ManagedCompiler.cs +++ b/src/dotnet/commands/dotnet-compile/ManagedCompiler.cs @@ -114,7 +114,7 @@ namespace Microsoft.DotNet.Tools.Compiler var dependencyContext = new DependencyContextBuilder().Build(compilationOptions, allExports, allExports, - string.IsNullOrEmpty(context.RuntimeIdentifier), + args.PortableMode, context.TargetFramework, context.RuntimeIdentifier ?? string.Empty); From ccf1a8bb39bf4d2fcff14715c565b9cc9d1e269d Mon Sep 17 00:00:00 2001 From: Sridhar Periyasamy Date: Thu, 10 Mar 2016 11:41:18 -0800 Subject: [PATCH 27/31] Update the version badges links to point to new URIs. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 790d84169..6bc696ff8 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Installers | |Ubuntu 14.04 |Windows |Mac OS X |CentOS 7.1 | |---------|:------:|:------:|:------:|:------:| -|**Version**|![](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/ubuntu_Release_version_badge.svg?nocache)|![](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/windows_Release_version_badge.svg?nocache)|![](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/osx_Release_version_badge.svg?nocache)|![](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/centos_Release_version_badge.svg?nocache)| +|**Version**|![](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/Ubuntu_x64_Release_version_badge.svg?nocache)|![](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/Windows_x64_Release_version_badge.svg?nocache)|![](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/OSX_x64_Release_version_badge.svg?nocache)|![](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/CentOS_x64_Release_version_badge.svg?nocache)| |**Installers**|[Download Debian Package](https://dotnetcli.blob.core.windows.net/dotnet/beta/Installers/Latest/dotnet-ubuntu-x64.latest.deb)|[Download Msi](https://dotnetcli.blob.core.windows.net/dotnet/beta/Installers/Latest/dotnet-win-x64.latest.exe)|[Download Pkg](https://dotnetcli.blob.core.windows.net/dotnet/beta/Installers/Latest/dotnet-osx-x64.latest.pkg) |N/A | |**Binaries**|[Download tar file](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/dotnet-ubuntu-x64.latest.tar.gz)|[Download zip file](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/dotnet-win-x64.latest.zip)|[Download tar file](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/dotnet-osx-x64.latest.tar.gz) |[Download tar file](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/dotnet-centos-x64.latest.tar.gz) | From a50a5a9d73ca892800e95eecab3625a88c04051b Mon Sep 17 00:00:00 2001 From: Troy Dai Date: Thu, 10 Mar 2016 00:47:13 -0800 Subject: [PATCH 28/31] Retry when lock file is occupied by other process --- .../Graph/LockFileReader.cs | 4 +- .../Utilities/ResilientFileStreamOpener.cs | 45 +++++++++++++ .../WorkspaceContext.cs | 20 +++++- .../DthTests.cs | 64 ++++++++++++++++--- 4 files changed, 120 insertions(+), 13 deletions(-) create mode 100644 src/Microsoft.DotNet.ProjectModel/Utilities/ResilientFileStreamOpener.cs diff --git a/src/Microsoft.DotNet.ProjectModel/Graph/LockFileReader.cs b/src/Microsoft.DotNet.ProjectModel/Graph/LockFileReader.cs index ad9bb0742..cb9d176dd 100644 --- a/src/Microsoft.DotNet.ProjectModel/Graph/LockFileReader.cs +++ b/src/Microsoft.DotNet.ProjectModel/Graph/LockFileReader.cs @@ -17,7 +17,7 @@ namespace Microsoft.DotNet.ProjectModel.Graph { public static LockFile Read(string lockFilePath) { - using (var stream = new FileStream(lockFilePath, FileMode.Open, FileAccess.Read, FileShare.Read)) + using (var stream = ResilientFileStreamOpener.OpenFile(lockFilePath)) { try { @@ -34,7 +34,7 @@ namespace Microsoft.DotNet.ProjectModel.Graph } } - internal static LockFile Read(string lockFilePath, Stream stream) + public static LockFile Read(string lockFilePath, Stream stream) { try { diff --git a/src/Microsoft.DotNet.ProjectModel/Utilities/ResilientFileStreamOpener.cs b/src/Microsoft.DotNet.ProjectModel/Utilities/ResilientFileStreamOpener.cs new file mode 100644 index 000000000..4a11904cb --- /dev/null +++ b/src/Microsoft.DotNet.ProjectModel/Utilities/ResilientFileStreamOpener.cs @@ -0,0 +1,45 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.IO; +using System.Threading; + +namespace Microsoft.DotNet.ProjectModel.Utilities +{ + public class ResilientFileStreamOpener + { + public static FileStream OpenFile(string filepath) + { + return OpenFile(filepath, 0); + } + + public static FileStream OpenFile(string filepath, int retry) + { + if (retry < 0) + { + throw new ArgumentException("Retry can't be fewer than 0", nameof(retry)); + } + + var count = 0; + while (true) + { + try + { + return new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.Read); + } + catch + { + if (++count > retry) + { + throw; + } + else + { + Thread.Sleep(500); + } + } + } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.ProjectModel/WorkspaceContext.cs b/src/Microsoft.DotNet.ProjectModel/WorkspaceContext.cs index f046143f7..f152a3795 100644 --- a/src/Microsoft.DotNet.ProjectModel/WorkspaceContext.cs +++ b/src/Microsoft.DotNet.ProjectModel/WorkspaceContext.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.DotNet.ProjectModel.Utilities; namespace Microsoft.DotNet.ProjectModel { @@ -205,8 +206,23 @@ namespace Microsoft.DotNet.ProjectModel else { currentEntry.FilePath = Path.Combine(projectDirectory, LockFile.FileName); - currentEntry.Model = LockFileReader.Read(currentEntry.FilePath); - currentEntry.UpdateLastWriteTimeUtc(); + + using (var fs = ResilientFileStreamOpener.OpenFile(currentEntry.FilePath, retry: 2)) + { + try + { + currentEntry.Model = LockFileReader.Read(currentEntry.FilePath, fs); + currentEntry.UpdateLastWriteTimeUtc(); + } + catch (FileFormatException ex) + { + throw ex.WithFilePath(currentEntry.FilePath); + } + catch (Exception ex) + { + throw FileFormatException.Create(ex, currentEntry.FilePath); + } + } } } diff --git a/test/dotnet-projectmodel-server.Tests/DthTests.cs b/test/dotnet-projectmodel-server.Tests/DthTests.cs index 9a38ac4f8..1813772d3 100644 --- a/test/dotnet-projectmodel-server.Tests/DthTests.cs +++ b/test/dotnet-projectmodel-server.Tests/DthTests.cs @@ -4,6 +4,9 @@ using System; using System.IO; using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.DotNet.ProjectModel.Graph; using Microsoft.DotNet.TestFramework; using Microsoft.DotNet.Tools.Test.Utilities; using Microsoft.Extensions.Logging; @@ -18,7 +21,7 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests { private readonly TestAssetsManager _testAssetsManager; private readonly ILoggerFactory _loggerFactory; - + public DthTests() { _loggerFactory = new LoggerFactory(); @@ -32,11 +35,11 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests { _loggerFactory.AddConsole(LogLevel.Information); } - else + else if (testVerbose == "0") { _loggerFactory.AddConsole(LogLevel.Warning); } - + _testAssetsManager = new TestAssetsManager( Path.Combine(RepoRoot, "TestAssets", "ProjectModelServer", "DthTestProjects", "src")); } @@ -118,7 +121,7 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests Console.WriteLine("Test is skipped on Linux"); return; } - + var projectPath = Path.Combine(_testAssetsManager.AssetsRoot, testProjectName); Assert.NotNull(projectPath); @@ -292,7 +295,7 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests var testAssetsPath = Path.Combine(RepoRoot, "TestAssets", "ProjectModelServer"); var assetsManager = new TestAssetsManager(testAssetsPath); var testSource = assetsManager.CreateTestInstance("IncorrectProjectJson").TestRoot; - + using (var server = new DthTestServer(_loggerFactory)) using (var client = new DthTestClient(server)) { @@ -337,30 +340,73 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests .AssertProperty("Path", v => v.Contains("InvalidGlobalJson")); } } - + [Fact] public void RecoverFromGlobalError() { var testProject = _testAssetsManager.CreateTestInstance("EmptyConsoleApp") .WithLockFiles() .TestRoot; - + using (var server = new DthTestServer(_loggerFactory)) using (var client = new DthTestClient(server)) { var projectFile = Path.Combine(testProject, Project.FileName); var content = File.ReadAllText(projectFile); File.WriteAllText(projectFile, content + "}"); - + client.Initialize(testProject); var messages = client.DrainAllMessages(); messages.ContainsMessage(MessageTypes.Error); - + File.WriteAllText(projectFile, content); client.SendPayLoad(testProject, MessageTypes.FilesChanged); var clearError = client.DrainTillFirst(MessageTypes.Error); clearError.Payload.AsJObject().AssertProperty("Message", null as string); } } + + [Theory] + [InlineData(500, true)] + [InlineData(3000, false)] + public void WaitForLockFileReleased(int occupyFileFor, bool expectSuccess) + { + var testProject = _testAssetsManager.CreateTestInstance("EmptyConsoleApp") + .WithLockFiles() + .TestRoot; + + using (var server = new DthTestServer(_loggerFactory)) + using (var client = new DthTestClient(server)) + { + var lockFilePath = Path.Combine(testProject, LockFile.FileName); + var lockFileContent = File.ReadAllText(lockFilePath); + var fs = new FileStream(lockFilePath, FileMode.Create, FileAccess.Write, FileShare.None); + + // Test the platform + // A sharing violation is expected in following code. Otherwise the FileSteam is not implemented correctly. + Assert.ThrowsAny(() => + { + new FileStream(lockFilePath, FileMode.Open, FileAccess.Read, FileShare.Read); + }); + + var task = Task.Run(() => + { + // WorkspaceContext will try to open the lock file for 3 times with 500 ms interval in between. + Thread.Sleep(occupyFileFor); + fs.Dispose(); + }); + + client.Initialize(testProject); + var messages = client.DrainAllMessages(); + if (expectSuccess) + { + messages.AssertDoesNotContain(MessageTypes.Error); + } + else + { + messages.ContainsMessage(MessageTypes.Error); + } + } + } } } From 76262b8b0a371a4c372d35ff9509c20adffdf3b0 Mon Sep 17 00:00:00 2001 From: Troy Dai Date: Thu, 10 Mar 2016 12:47:00 -0800 Subject: [PATCH 29/31] Fix build break on osx.10.11 --- TestAssets/TestProjects/BuildTestStandaloneProject/project.json | 1 + 1 file changed, 1 insertion(+) diff --git a/TestAssets/TestProjects/BuildTestStandaloneProject/project.json b/TestAssets/TestProjects/BuildTestStandaloneProject/project.json index 8d366cf72..5aff9ad77 100644 --- a/TestAssets/TestProjects/BuildTestStandaloneProject/project.json +++ b/TestAssets/TestProjects/BuildTestStandaloneProject/project.json @@ -15,6 +15,7 @@ "win7-x64": {}, "win7-x86": {}, "osx.10.10-x64": {}, + "osx.10.11-x64": {}, "ubuntu.14.04-x64": {}, "centos.7-x64": {}, "rhel.7.2-x64": {}, From 5214d176cd5081967f444c4f0f4684d9cd64153b Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Thu, 10 Mar 2016 12:18:05 -0800 Subject: [PATCH 30/31] Fix issue with paths in deps.json not being normalized to have /, also moves rid graph section to root leve instead of being inside arget subsection --- .../DependencyContextWriter.cs | 27 +++++++++++-------- .../DependencyContextJsonWriterTests.cs | 11 +++----- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs index 18dea9304..2f26e8c49 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs @@ -27,13 +27,17 @@ namespace Microsoft.Extensions.DependencyModel private JObject Write(DependencyContext context) { - return new JObject( + var contextObject = new JObject( new JProperty(DependencyContextStrings.RuntimeTargetPropertyName, WriteRuntimeTargetInfo(context)), new JProperty(DependencyContextStrings.CompilationOptionsPropertName, WriteCompilationOptions(context.CompilationOptions)), new JProperty(DependencyContextStrings.TargetsPropertyName, WriteTargets(context)), - new JProperty(DependencyContextStrings.LibrariesPropertyName, WriteLibraries(context)), - new JProperty(DependencyContextStrings.RuntimesPropertyName, WriteRuntimeGraph(context)) + new JProperty(DependencyContextStrings.LibrariesPropertyName, WriteLibraries(context)) ); + if (context.RuntimeGraph.Any()) + { + contextObject.Add(new JProperty(DependencyContextStrings.RuntimesPropertyName, WriteRuntimeGraph(context))); + } + return contextObject; } private string WriteRuntimeTargetInfo(DependencyContext context) @@ -46,11 +50,7 @@ namespace Microsoft.Extensions.DependencyModel private JObject WriteRuntimeGraph(DependencyContext context) { return new JObject( - new JProperty(context.TargetFramework, - new JObject( - context.RuntimeGraph.Select(g => new JProperty(g.Key, new JArray(g.Value))) - ) - ) + context.RuntimeGraph.Select(g => new JProperty(g.Key, new JArray(g.Value))) ); } @@ -183,7 +183,7 @@ namespace Microsoft.Extensions.DependencyModel } libraryObject.Add(DependencyContextStrings.ResourceAssembliesPropertyName, new JObject(resourceAssemblies.Select(a => - new JProperty(a.Path, new JObject(new JProperty(DependencyContextStrings.LocalePropertyName, a.Locale)))) + new JProperty(NormalizePath(a.Path), new JObject(new JProperty(DependencyContextStrings.LocalePropertyName, a.Locale)))) ) ); } @@ -263,7 +263,7 @@ namespace Microsoft.Extensions.DependencyModel { foreach (var assembly in assemblies) { - yield return new JProperty(assembly, + yield return new JProperty(NormalizePath(assembly), new JObject( new JProperty(DependencyContextStrings.RidPropertyName, runtime), new JProperty(DependencyContextStrings.AssetTypePropertyName, assetType) @@ -274,7 +274,7 @@ namespace Microsoft.Extensions.DependencyModel private JObject WriteAssemblies(IEnumerable assemblies) { - return new JObject(assemblies.Select(assembly => new JProperty(assembly, new JObject()))); + return new JObject(assemblies.Select(assembly => new JProperty(NormalizePath(assembly), new JObject()))); } private JObject WriteLibraries(DependencyContext context) @@ -294,5 +294,10 @@ namespace Microsoft.Extensions.DependencyModel new JProperty(DependencyContextStrings.Sha512PropertyName, library.Hash) ); } + + private string NormalizePath(string path) + { + return path.Replace('\\', '/'); + } } } diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs index 2c0b76840..cafc90bf2 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs @@ -62,10 +62,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests new KeyValuePair("win8-x64", new [] { "win7-x64"}), })); - var runtimes = result.Should().HaveProperty("runtimes") - .Subject.Should().BeOfType().Subject; - - var rids = runtimes.Should().HaveProperty("Target") + var rids = result.Should().HaveProperty("runtimes") .Subject.Should().BeOfType().Subject; rids.Should().HaveProperty("win7-x64") @@ -159,7 +156,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests { new RuntimeTarget("win7-x64", new [] { RuntimeAssembly.Create("Banana.Win7-x64.dll") }, - new [] { "Banana.Win7-x64.so" } + new [] { "native\\Banana.Win7-x64.so" } ) }, new [] { @@ -184,12 +181,12 @@ namespace Microsoft.Extensions.DependencyModel.Tests runtimeAssembly.Should().HavePropertyValue("rid", "win7-x64"); runtimeAssembly.Should().HavePropertyValue("assetType", "runtime"); - var nativeLibrary = runtimeTargets.Should().HavePropertyAsObject("Banana.Win7-x64.so").Subject; + var nativeLibrary = runtimeTargets.Should().HavePropertyAsObject("native/Banana.Win7-x64.so").Subject; nativeLibrary.Should().HavePropertyValue("rid", "win7-x64"); nativeLibrary.Should().HavePropertyValue("assetType", "native"); var resourceAssemblies = library.Should().HavePropertyAsObject("resources").Subject; - var resourceAssembly = resourceAssemblies.Should().HavePropertyAsObject("en-US\\Banana.Resource.dll").Subject; + var resourceAssembly = resourceAssemblies.Should().HavePropertyAsObject("en-US/Banana.Resource.dll").Subject; resourceAssembly.Should().HavePropertyValue("locale", "en-US"); //libraries From dc3c00d660bcb9cda4bb7353873f2d8ba865606f Mon Sep 17 00:00:00 2001 From: Sridhar Periyasamy Date: Thu, 10 Mar 2016 16:03:43 -0800 Subject: [PATCH 31/31] Do not cache version badges in the blob storage. --- scripts/dotnet-cli-build/PublishTargets.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/dotnet-cli-build/PublishTargets.cs b/scripts/dotnet-cli-build/PublishTargets.cs index 8c1324c20..06dca3485 100644 --- a/scripts/dotnet-cli-build/PublishTargets.cs +++ b/scripts/dotnet-cli-build/PublishTargets.cs @@ -159,6 +159,7 @@ namespace Microsoft.DotNet.Cli.Build if (Path.GetExtension(blockBlob.Uri.AbsolutePath.ToLower()) == ".svg") { blockBlob.Properties.ContentType = "image/svg+xml"; + blockBlob.Properties.CacheControl = "no-cache"; blockBlob.SetPropertiesAsync().Wait(); } }