diff --git a/.vsts-ci.yml b/.vsts-ci.yml index 4df98acf9b18..33149faf36cd 100644 --- a/.vsts-ci.yml +++ b/.vsts-ci.yml @@ -3,26 +3,30 @@ trigger: - release/* variables: - teamName: Roslyn-Project-System - ${{ if eq(variables['System.TeamProject'], 'public') }}: - PB_PublishBlobFeedKey: - PB_PublishBlobFeedUrl: - _DotNetPublishToBlobFeed: false - ${{ if ne(variables['System.TeamProject'], 'public') }}: - PB_PublishBlobFeedUrl: https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json - _DotNetPublishToBlobFeed: true + - name: teamName + value: Roslyn-Project-System + - name: PB_PublishBlobFeedUrl + value: '' + - name: _DotNetPublishToBlobFeed + value: false + - ${{ if ne(variables['System.TeamProject'], 'public') }}: + - name: PB_PublishBlobFeedUrl + value: https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json + - name: _DotNetPublishToBlobFeed + value: true -phases: +jobs: - template: /eng/build.yml parameters: agentOs: Windows_NT - queue: + pool: ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: dotnet-external-temp + name: NetCorePublic-Int-Pool + queue: buildpool.windows.10.amd64.vs2017.open ${{ if ne(variables['System.TeamProject'], 'public') }}: - name: dotnet-internal-temp - parallel: 2 - timeoutInMinutes: 120 + name: NetCoreInternal-Int-Pool + queue: buildpool.windows.10.amd64.vs2017 + strategy: matrix: ${{ if eq(variables['System.TeamProject'], 'public') }}: Build_Debug: @@ -42,10 +46,10 @@ phases: - template: /eng/build.yml parameters: agentOs: Windows_NT_FullFramework - queue: - name: dotnet-external-temp - parallel: 2 - timeoutInMinutes: 120 + pool: + name: NetCorePublic-Int-Pool + queue: buildpool.windows.10.amd64.vs2017.open + strategy: matrix: Build_Debug: _BuildConfig: Debug @@ -59,10 +63,10 @@ phases: - template: /eng/build.yml parameters: agentOs: Windows_NT_TestAsTools - queue: - name: dotnet-external-temp - parallel: 2 - timeoutInMinutes: 120 + pool: + name: NetCorePublic-Int-Pool + queue: buildpool.windows.10.amd64.vs2017.open + strategy: matrix: Build_Debug: _BuildConfig: Debug @@ -72,10 +76,9 @@ phases: - template: /eng/build.yml parameters: agentOs: Ubuntu_14_04 - queue: + pool: name: Hosted Ubuntu 1604 - parallel: 2 - timeoutInMinutes: 120 + strategy: matrix: Build_Debug: _BuildConfig: Debug @@ -91,10 +94,9 @@ phases: - template: /eng/build.yml parameters: agentOs: Ubuntu_16_04 - queue: + pool: name: Hosted Ubuntu 1604 - parallel: 2 - timeoutInMinutes: 120 + strategy: matrix: Build_Debug: _BuildConfig: Debug @@ -110,10 +112,9 @@ phases: - template: /eng/build.yml parameters: agentOs: Darwin - queue: + pool: name: DotNetCore-Mac - parallel: 2 - timeoutInMinutes: 120 + strategy: matrix: Build_Debug: _BuildConfig: Debug @@ -127,10 +128,10 @@ phases: - template: /eng/build.yml parameters: agentOs: Windows_Performance - queue: - name: dotnet-external-temp - parallel: 2 - timeoutInMinutes: 120 + pool: + name: NetCorePublic-Int-Pool + queue: buildpool.windows.10.amd64.vs2017.open + strategy: matrix: Build_Release: _BuildConfig: Release @@ -140,10 +141,9 @@ phases: - template: /eng/build.yml parameters: agentOs: Linux_Performance - queue: + pool: name: Hosted Ubuntu 1604 - parallel: 2 - timeoutInMinutes: 120 + strategy: matrix: Build_Release: _BuildConfig: Release diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 78a9b8047261..4c8ce2d9ead8 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,13 +3,13 @@ - + https://github.com/dotnet/arcade - 9d8abf998866f10bc19d97e1916ff1c0ada3fd42 + 5e7ce5b394f3477bb0a485a4b761b7742e95be37 - + https://github.com/dotnet/arcade - 9d8abf998866f10bc19d97e1916ff1c0ada3fd42 + 5e7ce5b394f3477bb0a485a4b761b7742e95be37 diff --git a/eng/Versions.props b/eng/Versions.props index 99592248df6b..d8492eb0e493 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -7,22 +7,24 @@ 3.0.100 - preview4 + preview5 + 15.4.8 15.4.8 15.4.8 2.1.0-preview2-26306-03 + 3.0.0-preview5-27615-04 2.0.1-servicing-26011-01 9.0.1 - 5.0.1-rtm.5946 + 5.1.0-rtm.5921 $(NuGetBuildTasksPackVersion) $(NuGetBuildTasksPackVersion) 2.0.0 4.0.0 1.5.0 - 1.0.0-beta.19206.5 + 1.0.0-beta.19218.7 diff --git a/eng/build.yml b/eng/build.yml index fc00a1fc22b9..f0e23c0ddf76 100644 --- a/eng/build.yml +++ b/eng/build.yml @@ -1,53 +1,55 @@ parameters: + # Agent OS identifier and used as job name agentOs: '' - queue: {} + + # Agent pool + pool: {} + + # Additional variables variables: {} -phases: -- template: /eng/common/templates/phases/base.yml + # Build strategy - matrix + strategy: '' + + # Job timeout + timeoutInMinutes: 120 + +jobs: +- template: /eng/common/templates/job/job.yml parameters: name: ${{ parameters.agentOs }} - enableTelemetry: true enableMicrobuild: true - queue: ${{ parameters.queue }} + enablePublishBuildArtifacts: true + enablePublishBuildAssets: true + enablePublishTestResults: true + enableTelemetry: true + helixRepo: dotnet/sdk + pool: ${{ parameters.pool }} + timeoutInMinutes: ${{ parameters.timeoutInMinutes }} + ${{ if ne(parameters.strategy, '') }}: + strategy: ${{ parameters.strategy }} variables: - ${{ insert }}: ${{ parameters.variables }} - _AgentOSName: ${{ parameters.agentOs }} - _HelixType: build/product - _HelixBuildConfig: $(_BuildConfig) - _TeamName: DotNetCore - _PerformanceArgs: /p:PerfIterations=4 - ${{ if eq(variables['System.TeamProject'], 'public') }}: - _HelixSource: pr/dotnet/sdk/$(Build.SourceBranch) - _OfficialBuildIdArgs: '' - _PublishArgs: '' - _SignArgs: '' - ${{ if ne(variables['System.TeamProject'], 'public') }}: - _HelixSource: official/dotnet/sdk/$(Build.SourceBranch) - _OfficialBuildIdArgs: /p:OfficialBuildId=$(BUILD.BUILDNUMBER) - _PublishArgs: /p:DotNetPublishBlobFeedKey=$(dotnetfeed-storage-access-key-1) - /p:DotNetPublishBlobFeedUrl=$(PB_PublishBlobFeedUrl) - /p:DotNetPublishToBlobFeed=$(_DotNetPublishToBlobFeed) - /p:DotNetSymbolServerTokenMsdl=$(microsoft-symbol-server-pat) - /p:DotNetSymbolServerTokenSymWeb=$(symweb-symbol-server-pat) - /p:PB_PublishType=$(_PublishType) - _SignArgs: /p:DotNetSignType=$(_SignType) /p:TeamName=$(_TeamName) + - ${{ insert }}: ${{ parameters.variables }} + - _AgentOSName: ${{ parameters.agentOs }} + - _TeamName: DotNetCore + - _PerformanceArgs: /p:PerfIterations=4 + - _OfficialBuildIdArgs: '' + - _PublishArgs: '' + - _SignArgs: '' + - ${{ if ne(variables['System.TeamProject'], 'public') }}: + - group: DotNet-Symbol-Server-PATs + - group: DotNet-HelixApi-Access + - group: DotNet-Blob-Feed + - _OfficialBuildIdArgs: /p:OfficialBuildId=$(BUILD.BUILDNUMBER) + - _PublishArgs: /p:DotNetPublishBlobFeedKey=$(dotnetfeed-storage-access-key-1) + /p:DotNetPublishBlobFeedUrl=$(PB_PublishBlobFeedUrl) + /p:DotNetPublishToBlobFeed=$(_DotNetPublishToBlobFeed) + /p:DotNetSymbolServerTokenMsdl=$(microsoft-symbol-server-pat) + /p:DotNetSymbolServerTokenSymWeb=$(symweb-symbol-server-pat) + /p:PB_PublishType=$(_PublishType) + - _SignArgs: /p:DotNetSignType=$(_SignType) /p:TeamName=$(_TeamName) steps: - - ${{ if ne(variables['System.TeamProject'], 'public') }}: - - task: AzureKeyVault@1 - inputs: - azureSubscription: 'DotNet-Engineering-Services_KeyVault' - KeyVaultName: EngKeyVault - SecretsFilter: 'dotnetfeed-storage-access-key-1,microsoft-symbol-server-pat,symweb-symbol-server-pat' - condition: succeeded() - - task: AzureKeyVault@1 - inputs: - azureSubscription: 'HelixProd_KeyVault' - KeyVaultName: HelixProdKV - SecretsFilter: 'HelixApiAccessToken' - condition: always() - - ${{ if eq(parameters.agentOs, 'Windows_NT') }}: - script: eng\common\CIBuild.cmd -configuration $(_BuildConfig) @@ -116,33 +118,3 @@ phases: BuildConfig: $(_BuildConfig) BlobFeedUrl: $(PB_PublishBlobFeedUrl) PublishType: $(_PublishType) - - - task: PublishTestResults@1 - displayName: Publish Test Results - inputs: - testRunner: XUnit - testResultsFiles: 'artifacts/TestResults/$(_BuildConfig)/*.xml' - testRunTitle: '$(_AgentOSName)_$(Agent.JobName)' - platform: '$(BuildPlatform)' - configuration: '$(_BuildConfig)' - condition: not(succeeded()) - - - task: CopyFiles@2 - displayName: Gather Logs - inputs: - SourceFolder: '$(Build.SourcesDirectory)' - Contents: | - artifacts/log/$(_BuildConfig)/**/* - artifacts/TestResults/$(_BuildConfig)/**/* - TargetFolder: '$(Build.ArtifactStagingDirectory)' - continueOnError: true - condition: not(succeeded()) - - - task: PublishBuildArtifacts@1 - displayName: Publish Logs to VSTS - inputs: - PathtoPublish: '$(Build.ArtifactStagingDirectory)' - ArtifactName: '$(_AgentOSName)_$(Agent.JobName)_$(Build.BuildNumber)' - publishLocation: Container - continueOnError: true - condition: not(succeeded()) diff --git a/eng/common/CheckSymbols.ps1 b/eng/common/CheckSymbols.ps1 new file mode 100644 index 000000000000..b8d84607b89b --- /dev/null +++ b/eng/common/CheckSymbols.ps1 @@ -0,0 +1,158 @@ +param( + [Parameter(Mandatory=$true)][string] $InputPath, # Full path to directory where NuGet packages to be checked are stored + [Parameter(Mandatory=$true)][string] $ExtractPath, # Full path to directory where the packages will be extracted during validation + [Parameter(Mandatory=$true)][string] $SymbolToolPath # Full path to directory where dotnet symbol-tool was installed +) + +Add-Type -AssemblyName System.IO.Compression.FileSystem + +function FirstMatchingSymbolDescriptionOrDefault { + param( + [string] $FullPath, # Full path to the module that has to be checked + [string] $TargetServerParam, # Parameter to pass to `Symbol Tool` indicating the server to lookup for symbols + [string] $SymbolsPath + ) + + $FileName = [System.IO.Path]::GetFileName($FullPath) + $Extension = [System.IO.Path]::GetExtension($FullPath) + + # Those below are potential symbol files that the `dotnet symbol` might + # return. Which one will be returned depend on the type of file we are + # checking and which type of file was uploaded. + + # The file itself is returned + $SymbolPath = $SymbolsPath + "\" + $FileName + + # PDB file for the module + $PdbPath = $SymbolPath.Replace($Extension, ".pdb") + + # PDB file for R2R module (created by crossgen) + $NGenPdb = $SymbolPath.Replace($Extension, ".ni.pdb") + + # DBG file for a .so library + $SODbg = $SymbolPath.Replace($Extension, ".so.dbg") + + # DWARF file for a .dylib + $DylibDwarf = $SymbolPath.Replace($Extension, ".dylib.dwarf") + + .\dotnet-symbol.exe --symbols --modules --windows-pdbs $TargetServerParam $FullPath -o $SymbolsPath | Out-Null + + if (Test-Path $PdbPath) { + return "PDB" + } + elseif (Test-Path $NGenPdb) { + return "NGen PDB" + } + elseif (Test-Path $SODbg) { + return "DBG for SO" + } + elseif (Test-Path $DylibDwarf) { + return "Dwarf for Dylib" + } + elseif (Test-Path $SymbolPath) { + return "Module" + } + else { + return $null + } +} + +function CountMissingSymbols { + param( + [string] $PackagePath # Path to a NuGet package + ) + + # Ensure input file exist + if (!(Test-Path $PackagePath)) { + throw "Input file does not exist: $PackagePath" + } + + # Extensions for which we'll look for symbols + $RelevantExtensions = @(".dll", ".exe", ".so", ".dylib") + + # How many files are missing symbol information + $MissingSymbols = 0 + + $PackageId = [System.IO.Path]::GetFileNameWithoutExtension($PackagePath) + $PackageGuid = New-Guid + $ExtractPath = Join-Path -Path $ExtractPath -ChildPath $PackageGuid + $SymbolsPath = Join-Path -Path $ExtractPath -ChildPath "Symbols" + + [System.IO.Compression.ZipFile]::ExtractToDirectory($PackagePath, $ExtractPath) + + # Makes easier to reference `symbol tool` + Push-Location $SymbolToolPath + + Get-ChildItem -Recurse $ExtractPath | + Where-Object {$RelevantExtensions -contains $_.Extension} | + ForEach-Object { + if ($_.FullName -Match "\\ref\\") { + Write-Host "`t Ignoring reference assembly file" $_.FullName + return + } + + $SymbolsOnMSDL = FirstMatchingSymbolDescriptionOrDefault $_.FullName "--microsoft-symbol-server" $SymbolsPath + $SymbolsOnSymWeb = FirstMatchingSymbolDescriptionOrDefault $_.FullName "--internal-server" $SymbolsPath + + Write-Host -NoNewLine "`t Checking file" $_.FullName "... " + + if ($SymbolsOnMSDL -ne $null -and $SymbolsOnSymWeb -ne $null) { + Write-Host "Symbols found on MSDL (" $SymbolsOnMSDL ") and SymWeb (" $SymbolsOnSymWeb ")" + } + else { + $MissingSymbols++ + + if ($SymbolsOnMSDL -eq $null -and $SymbolsOnSymWeb -eq $null) { + Write-Host "No symbols found on MSDL or SymWeb!" + } + else { + if ($SymbolsOnMSDL -eq $null) { + Write-Host "No symbols found on MSDL!" + } + else { + Write-Host "No symbols found on SymWeb!" + } + } + } + } + + Pop-Location + + return $MissingSymbols +} + +function CheckSymbolsAvailable { + if (Test-Path $ExtractPath) { + Remove-Item $ExtractPath -Force -Recurse -ErrorAction SilentlyContinue + } + + Get-ChildItem "$InputPath\*.nupkg" | + ForEach-Object { + $FileName = $_.Name + + # These packages from Arcade-Services include some native libraries that + # our current symbol uploader can't handle. Below is a workaround until + # we get issue: https://github.com/dotnet/arcade/issues/2457 sorted. + if ($FileName -Match "Microsoft\.DotNet\.Darc\.") { + Write-Host "Ignoring Arcade-services file: $FileName" + Write-Host + return + } + elseif ($FileName -Match "Microsoft\.DotNet\.Maestro\.Tasks\.") { + Write-Host "Ignoring Arcade-services file: $FileName" + Write-Host + return + } + + Write-Host "Validating $FileName " + $Status = CountMissingSymbols "$InputPath\$FileName" + + if ($Status -ne 0) { + Write-Error "Missing symbols for $Status modules in the package $FileName" + } + + Write-Host + } +} + +CheckSymbolsAvailable diff --git a/eng/common/PublishToSymbolServers.proj b/eng/common/PublishToSymbolServers.proj index 36c08f0ea492..5d55e312b012 100644 --- a/eng/common/PublishToSymbolServers.proj +++ b/eng/common/PublishToSymbolServers.proj @@ -24,6 +24,14 @@ + + + + diff --git a/eng/common/internal/Tools.csproj b/eng/common/internal/Tools.csproj index 1a81ff906f6e..1a39a7ef3f67 100644 --- a/eng/common/internal/Tools.csproj +++ b/eng/common/internal/Tools.csproj @@ -12,8 +12,12 @@ - - https://devdiv.pkgs.visualstudio.com/_packaging/8f470c7e-ac49-4afe-a6ee-cf784e438b93/nuget/v3/index.json; + + + https://devdiv.pkgs.visualstudio.com/_packaging/dotnet-core-internal-tooling/nuget/v3/index.json; + + + $(RestoreSources); https://devdiv.pkgs.visualstudio.com/_packaging/VS/nuget/v3/index.json; diff --git a/eng/common/templates/phases/publish-build-assets.yml b/eng/common/templates/phases/publish-build-assets.yml index 211967debab5..a0a8074282aa 100644 --- a/eng/common/templates/phases/publish-build-assets.yml +++ b/eng/common/templates/phases/publish-build-assets.yml @@ -5,6 +5,7 @@ parameters: condition: succeeded() continueOnError: false runAsPublic: false + publishUsingPipelines: false phases: - phase: Asset_Registry_Publish displayName: Publish to Build Asset Registry @@ -36,6 +37,7 @@ phases: /p:ManifestsPath='$(Build.StagingDirectory)/Download/AssetManifests' /p:BuildAssetRegistryToken=$(MaestroAccessToken) /p:MaestroApiEndpoint=https://maestro-prod.westus2.cloudapp.azure.com + /p:PublishUsingPipelines=${{ parameters.publishUsingPipelines }} /p:Configuration=$(_BuildConfig) condition: ${{ parameters.condition }} continueOnError: ${{ parameters.continueOnError }} diff --git a/eng/dogfood.ps1 b/eng/dogfood.ps1 index 9df83a8a4bc6..3b43a6999458 100644 --- a/eng/dogfood.ps1 +++ b/eng/dogfood.ps1 @@ -14,6 +14,7 @@ $restore = $true . $PSScriptRoot\common\tools.ps1 +. $PSScriptRoot\configure-toolset.ps1 function Print-Usage() { Write-Host "Common settings:" diff --git a/eng/dogfood.sh b/eng/dogfood.sh index 8bd1df53dcad..b873e9d05d1a 100644 --- a/eng/dogfood.sh +++ b/eng/dogfood.sh @@ -9,6 +9,7 @@ done scriptroot="$( cd -P "$( dirname "$SOURCE" )" && pwd )" . "$scriptroot/common/tools.sh" +. "$scriptroot/configure-toolset.sh" InitializeToolset . "$scriptroot/restore-toolset.sh" diff --git a/global.json b/global.json index 7e2738422106..d3ffda95b27f 100644 --- a/global.json +++ b/global.json @@ -1,11 +1,11 @@ { "tools": { - "dotnet": "3.0.100-preview4-011172", + "dotnet": "3.0.100-preview5-011481", "vs-opt": { "version": "15.9" } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19206.5" + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19218.7" } } diff --git a/src/Assets/TestProjects/HelloWorldWithSubDirs/HelloWorldWithSubDirs.csproj b/src/Assets/TestProjects/HelloWorldWithSubDirs/HelloWorldWithSubDirs.csproj new file mode 100644 index 000000000000..c24b9a827154 --- /dev/null +++ b/src/Assets/TestProjects/HelloWorldWithSubDirs/HelloWorldWithSubDirs.csproj @@ -0,0 +1,18 @@ + + + + Exe + netcoreapp3.0 + + + + + PreserveNewest + + + PreserveNewest + $(ExcludeContent) + + + + diff --git a/src/Assets/TestProjects/HelloWorldWithSubDirs/Program.cs b/src/Assets/TestProjects/HelloWorldWithSubDirs/Program.cs new file mode 100644 index 000000000000..27469c19e660 --- /dev/null +++ b/src/Assets/TestProjects/HelloWorldWithSubDirs/Program.cs @@ -0,0 +1,17 @@ +using System; +using System.IO; +using System.Reflection; + +namespace HelloWorldWithSubDirs +{ + class Program + { + static void Main(string[] args) + { + string baseDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + string hello = File.ReadAllText(Path.Combine(baseDir, "SmallNameDir", "word")); + string world = File.ReadAllText(Path.Combine(baseDir, "SmallNameDir", "This is a directory with a really long name for one that only contains a small file", ".word")); + Console.WriteLine($"{hello} {world}"); + } + } +} diff --git a/src/Assets/TestProjects/HelloWorldWithSubDirs/Signature.stamp b/src/Assets/TestProjects/HelloWorldWithSubDirs/Signature.stamp new file mode 100644 index 000000000000..11cfda16d9b2 --- /dev/null +++ b/src/Assets/TestProjects/HelloWorldWithSubDirs/Signature.stamp @@ -0,0 +1 @@ +Signed by .Net Core SDK devs. \ No newline at end of file diff --git a/src/Assets/TestProjects/HelloWorldWithSubDirs/SmallNameDir/This is a directory with a really long name for one that only contains a small file/.word b/src/Assets/TestProjects/HelloWorldWithSubDirs/SmallNameDir/This is a directory with a really long name for one that only contains a small file/.word new file mode 100644 index 000000000000..e5b8f9cece33 --- /dev/null +++ b/src/Assets/TestProjects/HelloWorldWithSubDirs/SmallNameDir/This is a directory with a really long name for one that only contains a small file/.word @@ -0,0 +1 @@ +World! \ No newline at end of file diff --git a/src/Assets/TestProjects/HelloWorldWithSubDirs/SmallNameDir/word b/src/Assets/TestProjects/HelloWorldWithSubDirs/SmallNameDir/word new file mode 100644 index 000000000000..5ab2f8a4323a --- /dev/null +++ b/src/Assets/TestProjects/HelloWorldWithSubDirs/SmallNameDir/word @@ -0,0 +1 @@ +Hello \ No newline at end of file diff --git a/src/Tasks/Common/Resources/Strings.resx b/src/Tasks/Common/Resources/Strings.resx index 37a66d1d47e6..6b3b2cfbd2df 100644 --- a/src/Tasks/Common/Resources/Strings.resx +++ b/src/Tasks/Common/Resources/Strings.resx @@ -498,11 +498,23 @@ The following are names of parameters or literal values and should not be transl {StrBegin="NETSDK1094: "} - NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Either set the ReadyToRun property to false, or use a supported runtime identifier when publishing. + NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Please verify you are publishing a self-contained application using a supported runtime identifier, or set the ReadyToRun property to false. {StrBegin="NETSDK1095: "} NETSDK1096: Optimizing assemblies for performance failed. You can either exclude the failing assemblies from being optimized, or set the ReadyToRun property to false. {StrBegin="NETSDK1096: "} + + NETSDK1097: It is not supported to publish an application to a single-file without specifying a RuntimeIdentifier. Please either specify a RuntimeIdentifier or set PublishSingleFile to false. + {StrBegin="NETSDK1097: "} + + + NETSDK1098: Applications published to a single-file are required to use the application host. Please either set PublishSingleFile to false or set UseAppHost to true. + {StrBegin="NETSDK1098: "} + + + NETSDK1099: Publishing to a single-file is only supported for executable applications. + {StrBegin="NETSDK1099: "} + diff --git a/src/Tasks/Common/Resources/xlf/Strings.cs.xlf b/src/Tasks/Common/Resources/xlf/Strings.cs.xlf index 7b01d3ac6d12..b6c8a7a2975f 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.cs.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.cs.xlf @@ -107,6 +107,21 @@ NETSDK1031: Sestavení nebo publikování nezávislé aplikace bez zadání parametru RuntimeIdentifier není podporované. Zadejte prosím buď parametr RuntimeIdentifier, nebo nastavte parametr SelfContained na hodnotu False. {StrBegin="NETSDK1031: "} + + NETSDK1097: It is not supported to publish an application to a single-file without specifying a RuntimeIdentifier. Please either specify a RuntimeIdentifier or set PublishSingleFile to false. + NETSDK1097: It is not supported to publish an application to a single-file without specifying a RuntimeIdentifier. Please either specify a RuntimeIdentifier or set PublishSingleFile to false. + {StrBegin="NETSDK1097: "} + + + NETSDK1098: Applications published to a single-file are required to use the application host. Please either set PublishSingleFile to false or set UseAppHost to true. + NETSDK1098: Applications published to a single-file are required to use the application host. Please either set PublishSingleFile to false or set UseAppHost to true. + {StrBegin="NETSDK1098: "} + + + NETSDK1099: Publishing to a single-file is only supported for executable applications. + NETSDK1099: Publishing to a single-file is only supported for executable applications. + {StrBegin="NETSDK1099: "} + NETSDK1013: The TargetFramework value '{0}' was not recognized. It may be misspelled. If not, then the TargetFrameworkIdentifier and/or TargetFrameworkVersion properties must be specified explicitly. NETSDK1013: Hodnota TargetFramework {0} nebyla rozpoznána. Je možné, že obsahuje překlepy. Pokud tomu tak není, musíte vlastnosti TargetFrameworkIdentifier a TargetFrameworkVersion zadat explicitně. @@ -407,8 +422,8 @@ The following are names of parameters or literal values and should not be transl {StrBegin="NETSDK1094: "} - NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Either set the ReadyToRun property to false, or use a supported runtime identifier when publishing. - NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Either set the ReadyToRun property to false, or use a supported runtime identifier when publishing. + NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Please verify you are publishing a self-contained application using a supported runtime identifier, or set the ReadyToRun property to false. + NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Please verify you are publishing a self-contained application using a supported runtime identifier, or set the ReadyToRun property to false. {StrBegin="NETSDK1095: "} @@ -488,4 +503,4 @@ The following are names of parameters or literal values and should not be transl - \ No newline at end of file + diff --git a/src/Tasks/Common/Resources/xlf/Strings.de.xlf b/src/Tasks/Common/Resources/xlf/Strings.de.xlf index c275605150fc..a16414661a2b 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.de.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.de.xlf @@ -107,6 +107,21 @@ NETSDK1031: Das Erstellen oder Veröffentlichen einer eigenständigen Anwendung ohne die Angabe eines RuntimeIdentifier wird nicht unterstützt. Geben Sie entweder einen RuntimeIdentifier an, oder legen Sie für SelfContained "False" fest. {StrBegin="NETSDK1031: "} + + NETSDK1097: It is not supported to publish an application to a single-file without specifying a RuntimeIdentifier. Please either specify a RuntimeIdentifier or set PublishSingleFile to false. + NETSDK1097: It is not supported to publish an application to a single-file without specifying a RuntimeIdentifier. Please either specify a RuntimeIdentifier or set PublishSingleFile to false. + {StrBegin="NETSDK1097: "} + + + NETSDK1098: Applications published to a single-file are required to use the application host. Please either set PublishSingleFile to false or set UseAppHost to true. + NETSDK1098: Applications published to a single-file are required to use the application host. Please either set PublishSingleFile to false or set UseAppHost to true. + {StrBegin="NETSDK1098: "} + + + NETSDK1099: Publishing to a single-file is only supported for executable applications. + NETSDK1099: Publishing to a single-file is only supported for executable applications. + {StrBegin="NETSDK1099: "} + NETSDK1013: The TargetFramework value '{0}' was not recognized. It may be misspelled. If not, then the TargetFrameworkIdentifier and/or TargetFrameworkVersion properties must be specified explicitly. NETSDK1013: Der TargetFramework-Wert "{0}" wurde nicht erkannt. Unter Umständen ist die Schreibweise nicht korrekt. Andernfalls müssen die Eigenschaften TargetFrameworkIdentifier und/oder TargetFrameworkVersion explizit angegeben werden. @@ -407,8 +422,8 @@ The following are names of parameters or literal values and should not be transl {StrBegin="NETSDK1094: "} - NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Either set the ReadyToRun property to false, or use a supported runtime identifier when publishing. - NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Either set the ReadyToRun property to false, or use a supported runtime identifier when publishing. + NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Please verify you are publishing a self-contained application using a supported runtime identifier, or set the ReadyToRun property to false. + NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Please verify you are publishing a self-contained application using a supported runtime identifier, or set the ReadyToRun property to false. {StrBegin="NETSDK1095: "} @@ -488,4 +503,4 @@ The following are names of parameters or literal values and should not be transl - \ No newline at end of file + diff --git a/src/Tasks/Common/Resources/xlf/Strings.es.xlf b/src/Tasks/Common/Resources/xlf/Strings.es.xlf index c42c4e9bb341..167f0a7d6472 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.es.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.es.xlf @@ -107,6 +107,21 @@ NETSDK1031: No se admite compilar o publicar una aplicación autocontenida sin especificar un valor para RuntimeIdentifier. Especifique un valor para RuntimeIdentifier o establezca SelfContained en false. {StrBegin="NETSDK1031: "} + + NETSDK1097: It is not supported to publish an application to a single-file without specifying a RuntimeIdentifier. Please either specify a RuntimeIdentifier or set PublishSingleFile to false. + NETSDK1097: It is not supported to publish an application to a single-file without specifying a RuntimeIdentifier. Please either specify a RuntimeIdentifier or set PublishSingleFile to false. + {StrBegin="NETSDK1097: "} + + + NETSDK1098: Applications published to a single-file are required to use the application host. Please either set PublishSingleFile to false or set UseAppHost to true. + NETSDK1098: Applications published to a single-file are required to use the application host. Please either set PublishSingleFile to false or set UseAppHost to true. + {StrBegin="NETSDK1098: "} + + + NETSDK1099: Publishing to a single-file is only supported for executable applications. + NETSDK1099: Publishing to a single-file is only supported for executable applications. + {StrBegin="NETSDK1099: "} + NETSDK1013: The TargetFramework value '{0}' was not recognized. It may be misspelled. If not, then the TargetFrameworkIdentifier and/or TargetFrameworkVersion properties must be specified explicitly. NETSDK1013: El valor de TargetFramework "{0}" no se reconoció. Puede que esté mal escrito. Si este no es el caso, las propiedades TargetFrameworkIdentifier o TargetFrameworkVersion se deben especificar explícitamente. @@ -407,8 +422,8 @@ The following are names of parameters or literal values and should not be transl {StrBegin="NETSDK1094: "} - NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Either set the ReadyToRun property to false, or use a supported runtime identifier when publishing. - NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Either set the ReadyToRun property to false, or use a supported runtime identifier when publishing. + NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Please verify you are publishing a self-contained application using a supported runtime identifier, or set the ReadyToRun property to false. + NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Please verify you are publishing a self-contained application using a supported runtime identifier, or set the ReadyToRun property to false. {StrBegin="NETSDK1095: "} @@ -488,4 +503,4 @@ The following are names of parameters or literal values and should not be transl - \ No newline at end of file + diff --git a/src/Tasks/Common/Resources/xlf/Strings.fr.xlf b/src/Tasks/Common/Resources/xlf/Strings.fr.xlf index a1d55ffc7788..ed5cf37a14a6 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.fr.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.fr.xlf @@ -107,6 +107,21 @@ NETSDK1031: La génération ou la publication d'une application autonome sans spécification de RuntimeIdentifier n'est pas prise en charge. Spécifiez RuntimeIdentifier ou affectez la valeur false à SelfContained. {StrBegin="NETSDK1031: "} + + NETSDK1097: It is not supported to publish an application to a single-file without specifying a RuntimeIdentifier. Please either specify a RuntimeIdentifier or set PublishSingleFile to false. + NETSDK1097: It is not supported to publish an application to a single-file without specifying a RuntimeIdentifier. Please either specify a RuntimeIdentifier or set PublishSingleFile to false. + {StrBegin="NETSDK1097: "} + + + NETSDK1098: Applications published to a single-file are required to use the application host. Please either set PublishSingleFile to false or set UseAppHost to true. + NETSDK1098: Applications published to a single-file are required to use the application host. Please either set PublishSingleFile to false or set UseAppHost to true. + {StrBegin="NETSDK1098: "} + + + NETSDK1099: Publishing to a single-file is only supported for executable applications. + NETSDK1099: Publishing to a single-file is only supported for executable applications. + {StrBegin="NETSDK1099: "} + NETSDK1013: The TargetFramework value '{0}' was not recognized. It may be misspelled. If not, then the TargetFrameworkIdentifier and/or TargetFrameworkVersion properties must be specified explicitly. NETSDK1013: La valeur TargetFramework '{0}' n'a pas été reconnue. Elle est peut-être mal orthographiée. Sinon, vous devez spécifier explicitement les propriétés TargetFrameworkIdentifier et/ou TargetFrameworkVersion. @@ -407,8 +422,8 @@ The following are names of parameters or literal values and should not be transl {StrBegin="NETSDK1094: "} - NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Either set the ReadyToRun property to false, or use a supported runtime identifier when publishing. - NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Either set the ReadyToRun property to false, or use a supported runtime identifier when publishing. + NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Please verify you are publishing a self-contained application using a supported runtime identifier, or set the ReadyToRun property to false. + NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Please verify you are publishing a self-contained application using a supported runtime identifier, or set the ReadyToRun property to false. {StrBegin="NETSDK1095: "} @@ -488,4 +503,4 @@ The following are names of parameters or literal values and should not be transl - \ No newline at end of file + diff --git a/src/Tasks/Common/Resources/xlf/Strings.it.xlf b/src/Tasks/Common/Resources/xlf/Strings.it.xlf index cf6ac0d0c714..1b06248c68a7 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.it.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.it.xlf @@ -107,6 +107,21 @@ NETSDK1031: non è possibile compilare o pubblicare un'applicazione indipendente senza specificare un elemento RuntimeIdentifier. Specificare un elemento RuntimeIdentifier o impostare SelfContained su false. {StrBegin="NETSDK1031: "} + + NETSDK1097: It is not supported to publish an application to a single-file without specifying a RuntimeIdentifier. Please either specify a RuntimeIdentifier or set PublishSingleFile to false. + NETSDK1097: It is not supported to publish an application to a single-file without specifying a RuntimeIdentifier. Please either specify a RuntimeIdentifier or set PublishSingleFile to false. + {StrBegin="NETSDK1097: "} + + + NETSDK1098: Applications published to a single-file are required to use the application host. Please either set PublishSingleFile to false or set UseAppHost to true. + NETSDK1098: Applications published to a single-file are required to use the application host. Please either set PublishSingleFile to false or set UseAppHost to true. + {StrBegin="NETSDK1098: "} + + + NETSDK1099: Publishing to a single-file is only supported for executable applications. + NETSDK1099: Publishing to a single-file is only supported for executable applications. + {StrBegin="NETSDK1099: "} + NETSDK1013: The TargetFramework value '{0}' was not recognized. It may be misspelled. If not, then the TargetFrameworkIdentifier and/or TargetFrameworkVersion properties must be specified explicitly. NETSDK1013: il valore {0}' di TargetFramework non è stato riconosciuto. È possibile che sia stato digitato in modo errato. In caso contrario, le proprietà TargetFrameworkIdentifier e/o TargetFrameworkVersion devono essere specificate in modo esplicito. @@ -407,8 +422,8 @@ The following are names of parameters or literal values and should not be transl {StrBegin="NETSDK1094: "} - NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Either set the ReadyToRun property to false, or use a supported runtime identifier when publishing. - NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Either set the ReadyToRun property to false, or use a supported runtime identifier when publishing. + NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Please verify you are publishing a self-contained application using a supported runtime identifier, or set the ReadyToRun property to false. + NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Please verify you are publishing a self-contained application using a supported runtime identifier, or set the ReadyToRun property to false. {StrBegin="NETSDK1095: "} @@ -488,4 +503,4 @@ The following are names of parameters or literal values and should not be transl - \ No newline at end of file + diff --git a/src/Tasks/Common/Resources/xlf/Strings.ja.xlf b/src/Tasks/Common/Resources/xlf/Strings.ja.xlf index baaa29f91df1..1c4005ddd1e4 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.ja.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.ja.xlf @@ -107,6 +107,21 @@ NETSDK1031: RuntimeIdentifier を指定せずに自己完結型アプリケーションをビルドおよび発行することはサポートされていません。RuntimeIdentifier を指定するか SelfContained を false に設定してください。 {StrBegin="NETSDK1031: "} + + NETSDK1097: It is not supported to publish an application to a single-file without specifying a RuntimeIdentifier. Please either specify a RuntimeIdentifier or set PublishSingleFile to false. + NETSDK1097: It is not supported to publish an application to a single-file without specifying a RuntimeIdentifier. Please either specify a RuntimeIdentifier or set PublishSingleFile to false. + {StrBegin="NETSDK1097: "} + + + NETSDK1098: Applications published to a single-file are required to use the application host. Please either set PublishSingleFile to false or set UseAppHost to true. + NETSDK1098: Applications published to a single-file are required to use the application host. Please either set PublishSingleFile to false or set UseAppHost to true. + {StrBegin="NETSDK1098: "} + + + NETSDK1099: Publishing to a single-file is only supported for executable applications. + NETSDK1099: Publishing to a single-file is only supported for executable applications. + {StrBegin="NETSDK1099: "} + NETSDK1013: The TargetFramework value '{0}' was not recognized. It may be misspelled. If not, then the TargetFrameworkIdentifier and/or TargetFrameworkVersion properties must be specified explicitly. NETSDK1013: TargetFramework 値 '{0}' が認識されませんでした。つづりが間違っている可能性があります。間違っていない場合は、TargetFrameworkIdentifier または TargetFrameworkVersion プロパティ (あるいはその両方) を明示的に指定する必要があります。 @@ -407,8 +422,8 @@ The following are names of parameters or literal values and should not be transl {StrBegin="NETSDK1094: "} - NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Either set the ReadyToRun property to false, or use a supported runtime identifier when publishing. - NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Either set the ReadyToRun property to false, or use a supported runtime identifier when publishing. + NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Please verify you are publishing a self-contained application using a supported runtime identifier, or set the ReadyToRun property to false. + NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Please verify you are publishing a self-contained application using a supported runtime identifier, or set the ReadyToRun property to false. {StrBegin="NETSDK1095: "} @@ -488,4 +503,4 @@ The following are names of parameters or literal values and should not be transl - \ No newline at end of file + diff --git a/src/Tasks/Common/Resources/xlf/Strings.ko.xlf b/src/Tasks/Common/Resources/xlf/Strings.ko.xlf index 0154d4cb1146..6d1c9851a2a5 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.ko.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.ko.xlf @@ -107,6 +107,21 @@ NETSDK1031: RuntimeIdentifier를 지정하지 않으면 자체 포함 애플리케이션의 빌드 또는 게시가 지원되지 않습니다. RuntimeIdentifier를 지정하거나 SelfContained를 false로 설정하세요. {StrBegin="NETSDK1031: "} + + NETSDK1097: It is not supported to publish an application to a single-file without specifying a RuntimeIdentifier. Please either specify a RuntimeIdentifier or set PublishSingleFile to false. + NETSDK1097: It is not supported to publish an application to a single-file without specifying a RuntimeIdentifier. Please either specify a RuntimeIdentifier or set PublishSingleFile to false. + {StrBegin="NETSDK1097: "} + + + NETSDK1098: Applications published to a single-file are required to use the application host. Please either set PublishSingleFile to false or set UseAppHost to true. + NETSDK1098: Applications published to a single-file are required to use the application host. Please either set PublishSingleFile to false or set UseAppHost to true. + {StrBegin="NETSDK1098: "} + + + NETSDK1099: Publishing to a single-file is only supported for executable applications. + NETSDK1099: Publishing to a single-file is only supported for executable applications. + {StrBegin="NETSDK1099: "} + NETSDK1013: The TargetFramework value '{0}' was not recognized. It may be misspelled. If not, then the TargetFrameworkIdentifier and/or TargetFrameworkVersion properties must be specified explicitly. NETSDK1013: TargetFramework 값 '{0}'을(를) 인식하지 못했습니다. 철자가 틀렸을 수 있습니다. 그렇지 않은 경우 TargetFrameworkIdentifier 및/또는 TargetFrameworkVersion 속성을 명시적으로 지정해야 합니다. @@ -407,8 +422,8 @@ The following are names of parameters or literal values and should not be transl {StrBegin="NETSDK1094: "} - NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Either set the ReadyToRun property to false, or use a supported runtime identifier when publishing. - NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Either set the ReadyToRun property to false, or use a supported runtime identifier when publishing. + NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Please verify you are publishing a self-contained application using a supported runtime identifier, or set the ReadyToRun property to false. + NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Please verify you are publishing a self-contained application using a supported runtime identifier, or set the ReadyToRun property to false. {StrBegin="NETSDK1095: "} @@ -488,4 +503,4 @@ The following are names of parameters or literal values and should not be transl - \ No newline at end of file + diff --git a/src/Tasks/Common/Resources/xlf/Strings.pl.xlf b/src/Tasks/Common/Resources/xlf/Strings.pl.xlf index 42d4251d3ebb..0dea4520ce11 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.pl.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.pl.xlf @@ -107,6 +107,21 @@ NETSDK1031: Kompilowanie i publikowanie aplikacji autonomicznej bez określania elementu RuntimeIdentifier nie jest obsługiwane. Określ element RuntimeIdentifier lub ustaw wartość false dla elementu SelfContained. {StrBegin="NETSDK1031: "} + + NETSDK1097: It is not supported to publish an application to a single-file without specifying a RuntimeIdentifier. Please either specify a RuntimeIdentifier or set PublishSingleFile to false. + NETSDK1097: It is not supported to publish an application to a single-file without specifying a RuntimeIdentifier. Please either specify a RuntimeIdentifier or set PublishSingleFile to false. + {StrBegin="NETSDK1097: "} + + + NETSDK1098: Applications published to a single-file are required to use the application host. Please either set PublishSingleFile to false or set UseAppHost to true. + NETSDK1098: Applications published to a single-file are required to use the application host. Please either set PublishSingleFile to false or set UseAppHost to true. + {StrBegin="NETSDK1098: "} + + + NETSDK1099: Publishing to a single-file is only supported for executable applications. + NETSDK1099: Publishing to a single-file is only supported for executable applications. + {StrBegin="NETSDK1099: "} + NETSDK1013: The TargetFramework value '{0}' was not recognized. It may be misspelled. If not, then the TargetFrameworkIdentifier and/or TargetFrameworkVersion properties must be specified explicitly. NETSDK1013: Nie rozpoznano wartości „{0}” elementu TargetFramework. Być może wpisano ją niepoprawnie. Jeśli nie, należy jawnie określić właściwości TargetFrameworkIdentifier i/lub TargetFrameworkVersion. @@ -407,8 +422,8 @@ The following are names of parameters or literal values and should not be transl {StrBegin="NETSDK1094: "} - NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Either set the ReadyToRun property to false, or use a supported runtime identifier when publishing. - NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Either set the ReadyToRun property to false, or use a supported runtime identifier when publishing. + NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Please verify you are publishing a self-contained application using a supported runtime identifier, or set the ReadyToRun property to false. + NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Please verify you are publishing a self-contained application using a supported runtime identifier, or set the ReadyToRun property to false. {StrBegin="NETSDK1095: "} @@ -488,4 +503,4 @@ The following are names of parameters or literal values and should not be transl - \ No newline at end of file + diff --git a/src/Tasks/Common/Resources/xlf/Strings.pt-BR.xlf b/src/Tasks/Common/Resources/xlf/Strings.pt-BR.xlf index b1076ef10a4a..a148c162a105 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.pt-BR.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.pt-BR.xlf @@ -107,6 +107,21 @@ NETSDK1031: Não há suporte para criar ou publicar um aplicativo autossuficiente sem especificar um RuntimeIdentifier. Especifique um RuntimeIdentifier ou defina SelfContained como falso. {StrBegin="NETSDK1031: "} + + NETSDK1097: It is not supported to publish an application to a single-file without specifying a RuntimeIdentifier. Please either specify a RuntimeIdentifier or set PublishSingleFile to false. + NETSDK1097: It is not supported to publish an application to a single-file without specifying a RuntimeIdentifier. Please either specify a RuntimeIdentifier or set PublishSingleFile to false. + {StrBegin="NETSDK1097: "} + + + NETSDK1098: Applications published to a single-file are required to use the application host. Please either set PublishSingleFile to false or set UseAppHost to true. + NETSDK1098: Applications published to a single-file are required to use the application host. Please either set PublishSingleFile to false or set UseAppHost to true. + {StrBegin="NETSDK1098: "} + + + NETSDK1099: Publishing to a single-file is only supported for executable applications. + NETSDK1099: Publishing to a single-file is only supported for executable applications. + {StrBegin="NETSDK1099: "} + NETSDK1013: The TargetFramework value '{0}' was not recognized. It may be misspelled. If not, then the TargetFrameworkIdentifier and/or TargetFrameworkVersion properties must be specified explicitly. NETSDK1013: O valor '{0}' do TargetFramework não foi reconhecido. Ele pode ter sido escrito com ortografia incorreta. Caso contrário, as propriedades TargetFrameworkIdentifier e/ou TargetFrameworkVersion precisarão ser especificadas explicitamente. @@ -407,8 +422,8 @@ The following are names of parameters or literal values and should not be transl {StrBegin="NETSDK1094: "} - NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Either set the ReadyToRun property to false, or use a supported runtime identifier when publishing. - NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Either set the ReadyToRun property to false, or use a supported runtime identifier when publishing. + NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Please verify you are publishing a self-contained application using a supported runtime identifier, or set the ReadyToRun property to false. + NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Please verify you are publishing a self-contained application using a supported runtime identifier, or set the ReadyToRun property to false. {StrBegin="NETSDK1095: "} @@ -488,4 +503,4 @@ The following are names of parameters or literal values and should not be transl - \ No newline at end of file + diff --git a/src/Tasks/Common/Resources/xlf/Strings.ru.xlf b/src/Tasks/Common/Resources/xlf/Strings.ru.xlf index 070923553a48..5e003c82258d 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.ru.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.ru.xlf @@ -107,6 +107,21 @@ NETSDK1031: сборка или публикация автономного приложения без указания RuntimeIdentifier не поддерживается. Укажите RuntimeIdentifier или присвойте свойству SelfContained значение "false". {StrBegin="NETSDK1031: "} + + NETSDK1097: It is not supported to publish an application to a single-file without specifying a RuntimeIdentifier. Please either specify a RuntimeIdentifier or set PublishSingleFile to false. + NETSDK1097: It is not supported to publish an application to a single-file without specifying a RuntimeIdentifier. Please either specify a RuntimeIdentifier or set PublishSingleFile to false. + {StrBegin="NETSDK1097: "} + + + NETSDK1098: Applications published to a single-file are required to use the application host. Please either set PublishSingleFile to false or set UseAppHost to true. + NETSDK1098: Applications published to a single-file are required to use the application host. Please either set PublishSingleFile to false or set UseAppHost to true. + {StrBegin="NETSDK1098: "} + + + NETSDK1099: Publishing to a single-file is only supported for executable applications. + NETSDK1099: Publishing to a single-file is only supported for executable applications. + {StrBegin="NETSDK1099: "} + NETSDK1013: The TargetFramework value '{0}' was not recognized. It may be misspelled. If not, then the TargetFrameworkIdentifier and/or TargetFrameworkVersion properties must be specified explicitly. NETSDK1013: значение "{0}" в TargetFramework не распознано. Возможно, оно содержит опечатку. Если это не так, задайте свойства TargetFrameworkIdentifier и (или) TargetFrameworkVersion явным образом. @@ -407,8 +422,8 @@ The following are names of parameters or literal values and should not be transl {StrBegin="NETSDK1094: "} - NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Either set the ReadyToRun property to false, or use a supported runtime identifier when publishing. - NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Either set the ReadyToRun property to false, or use a supported runtime identifier when publishing. + NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Please verify you are publishing a self-contained application using a supported runtime identifier, or set the ReadyToRun property to false. + NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Please verify you are publishing a self-contained application using a supported runtime identifier, or set the ReadyToRun property to false. {StrBegin="NETSDK1095: "} @@ -488,4 +503,4 @@ The following are names of parameters or literal values and should not be transl - \ No newline at end of file + diff --git a/src/Tasks/Common/Resources/xlf/Strings.tr.xlf b/src/Tasks/Common/Resources/xlf/Strings.tr.xlf index 1c2cfe05be65..fb437b941a59 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.tr.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.tr.xlf @@ -107,6 +107,21 @@ NETSDK1031: Bir RuntimeIdentifier belirtilmeden, bağımsız çalışan uygulamanın derlenmesi veya yayımlanması desteklenmez. Lütfen bir RuntimeIdentifier belirtin veya SelfContained değerini false olarak ayarlayın. {StrBegin="NETSDK1031: "} + + NETSDK1097: It is not supported to publish an application to a single-file without specifying a RuntimeIdentifier. Please either specify a RuntimeIdentifier or set PublishSingleFile to false. + NETSDK1097: It is not supported to publish an application to a single-file without specifying a RuntimeIdentifier. Please either specify a RuntimeIdentifier or set PublishSingleFile to false. + {StrBegin="NETSDK1097: "} + + + NETSDK1098: Applications published to a single-file are required to use the application host. Please either set PublishSingleFile to false or set UseAppHost to true. + NETSDK1098: Applications published to a single-file are required to use the application host. Please either set PublishSingleFile to false or set UseAppHost to true. + {StrBegin="NETSDK1098: "} + + + NETSDK1099: Publishing to a single-file is only supported for executable applications. + NETSDK1099: Publishing to a single-file is only supported for executable applications. + {StrBegin="NETSDK1099: "} + NETSDK1013: The TargetFramework value '{0}' was not recognized. It may be misspelled. If not, then the TargetFrameworkIdentifier and/or TargetFrameworkVersion properties must be specified explicitly. NETSDK1013: '{0}' TargetFramework değeri tanınmadı. Yanlış yazılmış olabilir. Sorun bundan kaynaklanmıyorsa, TargetFrameworkIdentifier ve/veya TargetFrameworkVersion özelliklerinin açık bir şekilde belirtilmesi gerekir. @@ -407,8 +422,8 @@ The following are names of parameters or literal values and should not be transl {StrBegin="NETSDK1094: "} - NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Either set the ReadyToRun property to false, or use a supported runtime identifier when publishing. - NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Either set the ReadyToRun property to false, or use a supported runtime identifier when publishing. + NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Please verify you are publishing a self-contained application using a supported runtime identifier, or set the ReadyToRun property to false. + NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Please verify you are publishing a self-contained application using a supported runtime identifier, or set the ReadyToRun property to false. {StrBegin="NETSDK1095: "} @@ -488,4 +503,4 @@ The following are names of parameters or literal values and should not be transl - \ No newline at end of file + diff --git a/src/Tasks/Common/Resources/xlf/Strings.zh-Hans.xlf b/src/Tasks/Common/Resources/xlf/Strings.zh-Hans.xlf index 960dbf023a9c..6d0870609ede 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.zh-Hans.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.zh-Hans.xlf @@ -107,6 +107,21 @@ NETSDK1031: 不可在未指定 RuntimeIdentifier 的情况下生成或发布自包含应用程序。请指定 RuntimeIdentifier 或将 SelfContained 设置为 false。 {StrBegin="NETSDK1031: "} + + NETSDK1097: It is not supported to publish an application to a single-file without specifying a RuntimeIdentifier. Please either specify a RuntimeIdentifier or set PublishSingleFile to false. + NETSDK1097: It is not supported to publish an application to a single-file without specifying a RuntimeIdentifier. Please either specify a RuntimeIdentifier or set PublishSingleFile to false. + {StrBegin="NETSDK1097: "} + + + NETSDK1098: Applications published to a single-file are required to use the application host. Please either set PublishSingleFile to false or set UseAppHost to true. + NETSDK1098: Applications published to a single-file are required to use the application host. Please either set PublishSingleFile to false or set UseAppHost to true. + {StrBegin="NETSDK1098: "} + + + NETSDK1099: Publishing to a single-file is only supported for executable applications. + NETSDK1099: Publishing to a single-file is only supported for executable applications. + {StrBegin="NETSDK1099: "} + NETSDK1013: The TargetFramework value '{0}' was not recognized. It may be misspelled. If not, then the TargetFrameworkIdentifier and/or TargetFrameworkVersion properties must be specified explicitly. NETSDK1013: 未识别 TargetFramework 值“{0}”。可能是因为拼写错误。如果拼写正确,必须显式指定 TargetFrameworkIdentifier 和/或 TargetFrameworkVersion 属性。 @@ -407,8 +422,8 @@ The following are names of parameters or literal values and should not be transl {StrBegin="NETSDK1094: "} - NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Either set the ReadyToRun property to false, or use a supported runtime identifier when publishing. - NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Either set the ReadyToRun property to false, or use a supported runtime identifier when publishing. + NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Please verify you are publishing a self-contained application using a supported runtime identifier, or set the ReadyToRun property to false. + NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Please verify you are publishing a self-contained application using a supported runtime identifier, or set the ReadyToRun property to false. {StrBegin="NETSDK1095: "} @@ -488,4 +503,4 @@ The following are names of parameters or literal values and should not be transl - \ No newline at end of file + diff --git a/src/Tasks/Common/Resources/xlf/Strings.zh-Hant.xlf b/src/Tasks/Common/Resources/xlf/Strings.zh-Hant.xlf index 4b94020dc4bf..ac139148d1f3 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.zh-Hant.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.zh-Hant.xlf @@ -107,6 +107,21 @@ NETSDK1031: 不支援在未指定 RuntimeIdentifier 的情況下,建置或發行獨立的應用程式。請指定 RuntimeIdentifier,或將 SelfContained 設為 False。 {StrBegin="NETSDK1031: "} + + NETSDK1097: It is not supported to publish an application to a single-file without specifying a RuntimeIdentifier. Please either specify a RuntimeIdentifier or set PublishSingleFile to false. + NETSDK1097: It is not supported to publish an application to a single-file without specifying a RuntimeIdentifier. Please either specify a RuntimeIdentifier or set PublishSingleFile to false. + {StrBegin="NETSDK1097: "} + + + NETSDK1098: Applications published to a single-file are required to use the application host. Please either set PublishSingleFile to false or set UseAppHost to true. + NETSDK1098: Applications published to a single-file are required to use the application host. Please either set PublishSingleFile to false or set UseAppHost to true. + {StrBegin="NETSDK1098: "} + + + NETSDK1099: Publishing to a single-file is only supported for executable applications. + NETSDK1099: Publishing to a single-file is only supported for executable applications. + {StrBegin="NETSDK1099: "} + NETSDK1013: The TargetFramework value '{0}' was not recognized. It may be misspelled. If not, then the TargetFrameworkIdentifier and/or TargetFrameworkVersion properties must be specified explicitly. NETSDK1013: 無法辨識 TargetFramework 值 '{0}'。拼字可能有誤。若非此情況,即必須明確指定 TargetFrameworkIdentifier 及 (或) TargetFrameworkVersion 屬性。 @@ -407,8 +422,8 @@ The following are names of parameters or literal values and should not be transl {StrBegin="NETSDK1094: "} - NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Either set the ReadyToRun property to false, or use a supported runtime identifier when publishing. - NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Either set the ReadyToRun property to false, or use a supported runtime identifier when publishing. + NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Please verify you are publishing a self-contained application using a supported runtime identifier, or set the ReadyToRun property to false. + NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Please verify you are publishing a self-contained application using a supported runtime identifier, or set the ReadyToRun property to false. {StrBegin="NETSDK1095: "} @@ -488,4 +503,4 @@ The following are names of parameters or literal values and should not be transl - \ No newline at end of file + diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/ClsidMap.cs b/src/Tasks/Microsoft.NET.Build.Tasks/ClsidMap.cs index 8075190cf419..141d0d3134f4 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/ClsidMap.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/ClsidMap.cs @@ -39,7 +39,7 @@ public static void Create(MetadataReader metadataReader, string clsidMapPath) // Only public COM-visible classes can be exposed via the COM host. if (TypeIsPublic(metadataReader, definition) && TypeIsClass(metadataReader, definition) && IsComVisible(metadataReader, definition, isAssemblyComVisible)) { - string guid = GetTypeGuid(metadataReader, definition); + string guid = GetTypeGuid(metadataReader, definition).ToString("B"); if (clsidMap.ContainsKey(guid)) { @@ -177,7 +177,7 @@ private static CustomAttributeHandle GetComVisibleAttribute(MetadataReader reade return new CustomAttributeHandle(); } - private static string GetTypeGuid(MetadataReader reader, TypeDefinition type) + private static Guid GetTypeGuid(MetadataReader reader, TypeDefinition type) { // Find the class' GUID by reading the GuidAttribute value. // We do not support implicit runtime-generated GUIDs for the .NET Core COM host. @@ -189,7 +189,7 @@ private static string GetTypeGuid(MetadataReader reader, TypeDefinition type) if (reader.StringComparer.Equals(attributeType.Namespace, "System.Runtime.InteropServices") && reader.StringComparer.Equals(attributeType.Name, "GuidAttribute")) { CustomAttributeValue data = attribute.DecodeValue(new TypeResolver()); - return (string)data.FixedArguments[0].Value; + return Guid.Parse((string)data.FixedArguments[0].Value); } } throw new BuildErrorException(Strings.ClsidMapExportedTypesRequireExplicitGuid, GetTypeName(reader, type)); diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/GenerateBundle.cs b/src/Tasks/Microsoft.NET.Build.Tasks/GenerateBundle.cs new file mode 100644 index 000000000000..2a1cd546e953 --- /dev/null +++ b/src/Tasks/Microsoft.NET.Build.Tasks/GenerateBundle.cs @@ -0,0 +1,38 @@ +// 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 Microsoft.Build.Framework; +using Microsoft.NET.HostModel.Bundle; +using System; +using System.Collections.Generic; + +namespace Microsoft.NET.Build.Tasks +{ + public class GenerateBundle : TaskBase + { + [Required] + public ITaskItem[] FilesToBundle { get; set; } + [Required] + public string AppHostName { get; set; } + [Required] + public bool IncludeSymbols { get; set; } + [Required] + public string OutputDir { get; set; } + [Required] + public bool ShowDiagnosticOutput { get; set; } + + protected override void ExecuteCore() + { + var bundler = new Bundler(AppHostName, OutputDir, IncludeSymbols, ShowDiagnosticOutput); + var fileSpec = new List(FilesToBundle.Length); + + foreach (var item in FilesToBundle) + { + fileSpec.Add(new FileSpec(sourcePath: item.ItemSpec, + bundleRelativePath:item.GetMetadata(MetadataKeys.RelativePath))); + } + + bundler.GenerateBundle(fileSpec); + } + } +} diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/GenerateDepsFile.cs b/src/Tasks/Microsoft.NET.Build.Tasks/GenerateDepsFile.cs index b35d5a5969c6..a2dc8f1c3d7a 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/GenerateDepsFile.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/GenerateDepsFile.cs @@ -86,7 +86,7 @@ public class GenerateDepsFile : TaskBase public bool IncludeRuntimeFileVersions { get; set; } - public string DepsFileGenerationMode { get; set; } = "both"; + public string DepsFileGenerationMode { get; set; } = "new"; List _filesWritten = new List(); diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/Microsoft.NET.Build.Tasks.csproj b/src/Tasks/Microsoft.NET.Build.Tasks/Microsoft.NET.Build.Tasks.csproj index d437e1d12911..7d3f218b87c2 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/Microsoft.NET.Build.Tasks.csproj +++ b/src/Tasks/Microsoft.NET.Build.Tasks/Microsoft.NET.Build.Tasks.csproj @@ -41,9 +41,11 @@ + + @@ -102,6 +104,7 @@ + ..\%(Stage0SdkFile.SdkName)\%(Stage0SdkFile.RecursiveDir)%(Stage0SdkFile.Filename)%(Stage0SdkFile.Extension) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/PrepareForReadyToRunCompilation.cs b/src/Tasks/Microsoft.NET.Build.Tasks/PrepareForReadyToRunCompilation.cs index 76896d17f5fd..299c341dad1b 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/PrepareForReadyToRunCompilation.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/PrepareForReadyToRunCompilation.cs @@ -17,16 +17,13 @@ namespace Microsoft.NET.Build.Tasks { public class PrepareForReadyToRunCompilation : TaskBase { - public ITaskItem[] FilesToPublishAlways { get; set; } - public ITaskItem[] FilesToPublishPreserveNewest { get; set; } - public string[] ReadyToRunExcludeList { get; set; } - public bool ReadyToRunEmitSymbols { get; set; } + public ITaskItem[] FilesToPublish { get; set; } + public string[] ExcludeList { get; set; } + public bool EmitSymbols { get; set; } [Required] public string OutputPath { get; set; } [Required] - public string TargetFramework { get; set; } - [Required] public ITaskItem[] RuntimePacks { get; set; } [Required] public ITaskItem[] KnownFrameworkReferences { get; set; } @@ -41,37 +38,25 @@ public class PrepareForReadyToRunCompilation : TaskBase // Output lists of files to compile. Currently crossgen has to run in two steps, the first to generate the R2R image // and the second to create native PDBs for the compiled images (the output of the first step is an input to the second step) [Output] - public ITaskItem[] ReadyToRunCompileListPublishAlways => _compileListPublishAlways.ToArray(); - [Output] - public ITaskItem[] ReadyToRunSymbolsCompileListPublishAlways => _symbolsCompileListPublishAlways.ToArray(); - [Output] - public ITaskItem[] ReadyToRunCompileListPreserveNewest => _compileListPreserveNewest.ToArray(); + public ITaskItem[] ReadyToRunCompileList => _compileList.ToArray(); [Output] - public ITaskItem[] ReadyToRunSymbolsCompileListPreserveNewest => _symbolsCompileListPreserveNewest.ToArray(); + public ITaskItem[] ReadyToRunSymbolsCompileList => _symbolsCompileList.ToArray(); - // Output files to publish after compilation. These lists are equivalent to the input lists, but contain the new + // Output files to publish after compilation. These lists are equivalent to the input list, but contain the new // paths to the compiled R2R images and native PDBs. [Output] - public ITaskItem[] ReadyToRunFilesToPublishAlways => _r2rFilesPublishAlways.ToArray(); - [Output] - public ITaskItem[] ReadyToRunFilesToPreserveNewest => _r2rFilesPreserveNewest.ToArray(); - - private List _compileListPublishAlways = new List(); - private List _compileListPreserveNewest = new List(); + public ITaskItem[] ReadyToRunFilesToPublish => _r2rFiles.ToArray(); - private List _symbolsCompileListPublishAlways = new List(); - private List _symbolsCompileListPreserveNewest = new List(); + private List _compileList = new List(); + private List _symbolsCompileList = new List(); - private List _r2rFilesPublishAlways = new List(); - private List _r2rFilesPreserveNewest = new List(); + private List _r2rFiles = new List(); private string _runtimeIdentifier; private string _packagePath; private string _crossgenPath; private string _clrjitPath; - private string _platformAssembliesPath; private string _diasymreaderPath; - private string _pathSeparatorCharacter = ";"; private Architecture _targetArchitecture; @@ -123,8 +108,7 @@ protected override void ExecuteCore() CrossgenTool.SetMetadata("DiaSymReader", _diasymreaderPath); // Process input lists of files - ProcessInputFileList(FilesToPublishPreserveNewest, _compileListPreserveNewest, _symbolsCompileListPreserveNewest, _r2rFilesPreserveNewest); - ProcessInputFileList(FilesToPublishAlways, _compileListPublishAlways, _symbolsCompileListPublishAlways, _r2rFilesPublishAlways); + ProcessInputFileList(FilesToPublish, _compileList, _symbolsCompileList, _r2rFiles); } void ProcessInputFileList(ITaskItem[] inputFiles, List imageCompilationList, List symbolsCompilationList, List r2rFilesPublishList) @@ -146,7 +130,6 @@ void ProcessInputFileList(ITaskItem[] inputFiles, List imageCompilati // an input to the ReadyToRunCompiler task TaskItem r2rCompilationEntry = new TaskItem(file); r2rCompilationEntry.SetMetadata("OutputR2RImage", outputR2RImage); - r2rCompilationEntry.SetMetadata("PlatformAssembliesPaths", $"{_platformAssembliesPath}{_pathSeparatorCharacter}{Path.GetDirectoryName(file.ItemSpec)}"); r2rCompilationEntry.RemoveMetadata(MetadataKeys.OriginalItemSpec); imageCompilationList.Add(r2rCompilationEntry); @@ -158,10 +141,10 @@ void ProcessInputFileList(ITaskItem[] inputFiles, List imageCompilati r2rFilesPublishList.Add(r2rFileToPublish); // Note: ReadyToRun PDB/Map files are not needed for debugging. They are only used for profiling, therefore the default behavior is to not generate them - // unless an explicit ReadyToRunEmitSymbols flag is enabled by the app developer. There is also another way to profile that the runtime supports, which does + // unless an explicit PublishReadyToRunEmitSymbols flag is enabled by the app developer. There is also another way to profile that the runtime supports, which does // not rely on the native PDBs/Map files, so creating them is really an opt-in option, typically used by advanced users. // For debugging, only the IL PDBs are required. - if (ReadyToRunEmitSymbols) + if (EmitSymbols) { string outputPDBImageRelativePath = null, outputPDBImage = null, createPDBCommand = null; @@ -193,7 +176,6 @@ void ProcessInputFileList(ITaskItem[] inputFiles, List imageCompilati pdbCompilationEntry.ItemSpec = outputR2RImage; pdbCompilationEntry.SetMetadata("OutputPDBImage", outputPDBImage); pdbCompilationEntry.SetMetadata("CreatePDBCommand", createPDBCommand); - pdbCompilationEntry.SetMetadata("PlatformAssembliesPaths", $"{_platformAssembliesPath}{_pathSeparatorCharacter}{Path.GetDirectoryName(file.ItemSpec)}"); symbolsCompilationList.Add(pdbCompilationEntry); // This TaskItem corresponds to the output PDB image. It is equivalent to the input TaskItem, only the ItemSpec for it points to the new path @@ -211,11 +193,15 @@ void ProcessInputFileList(ITaskItem[] inputFiles, List imageCompilati bool InputFileEligibleForCompilation(ITaskItem file) { // Check if the file is explicitly excluded from being compiled - if (ReadyToRunExcludeList != null) + if (ExcludeList != null) { - foreach (var item in ReadyToRunExcludeList) + foreach (var item in ExcludeList) + { if (String.Compare(Path.GetFileName(file.ItemSpec), item, true) == 0) + { return false; + } + } } // Check to see if this is a valid ILOnly image that we can compile @@ -238,7 +224,7 @@ bool InputFileEligibleForCompilation(ITaskItem file) } // Skip reference assemblies and assemblies that reference winmds - if (ReferencesWinMD(mdReader) || IsReferenceAssembly(mdReader)) + if (ReferencesWinMD(mdReader) || IsReferenceAssembly(mdReader) || !HasILCode(pereader, mdReader)) { return false; } @@ -305,6 +291,20 @@ private bool ReferencesWinMD(MetadataReader mdReader) return false; } + private bool HasILCode(PEReader peReader, MetadataReader mdReader) + { + foreach (var methoddefHandle in mdReader.MethodDefinitions) + { + MethodDefinition methodDef = mdReader.GetMethodDefinition(methoddefHandle); + if (methodDef.RelativeVirtualAddress > 0) + { + return true; + } + } + + return false; + } + bool ExtractTargetPlatformAndArchitecture(string runtimeIdentifier, out string platform, out Architecture architecture) { platform = null; @@ -372,8 +372,6 @@ bool GetCrossgenComponentsPaths() } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { - _pathSeparatorCharacter = ":"; - if (_targetArchitecture == Architecture.Arm || _targetArchitecture == Architecture.Arm64) { // We only have x64 hosted crossgen for both ARM target architectures @@ -392,8 +390,6 @@ bool GetCrossgenComponentsPaths() } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { - _pathSeparatorCharacter = ":"; - // Only x64 supported for OSX if (_targetArchitecture != Architecture.X64 || RuntimeInformation.OSArchitecture != Architecture.X64) return false; @@ -407,10 +403,6 @@ bool GetCrossgenComponentsPaths() return false; } - _platformAssembliesPath = - Path.Combine(_packagePath, "runtimes", _runtimeIdentifier, "native") + _pathSeparatorCharacter + - Path.Combine(_packagePath, "runtimes", _runtimeIdentifier, "lib", TargetFramework); - return true; } } diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/RegFreeComManifest.cs b/src/Tasks/Microsoft.NET.Build.Tasks/RegFreeComManifest.cs index 65bec4e7f946..8e2b8ff2e4bb 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/RegFreeComManifest.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/RegFreeComManifest.cs @@ -20,13 +20,13 @@ internal static class RegFreeComManifest /// The name of the assembly. /// The name of the comhost library. /// The version of the assembly. - /// The path to the clasidmap file. + /// The path to the clsidmap file. /// The path to which to write the manifest. public static void CreateManifestFromClsidmap(string assemblyName, string comHostName, string assemblyVersion, string clsidMapPath, string comManifestPath) { - XNamespace ns = "urn:shemas-microsoft-com:asm.v1"; + XNamespace ns = "urn:schemas-microsoft-com:asm.v1"; - XElement manifest = new XElement(ns + "assembly", new XAttribute("mainfestVersion", "1.0")); + XElement manifest = new XElement(ns + "assembly", new XAttribute("manifestVersion", "1.0")); manifest.Add(new XElement(ns + "assemblyIdentity", new XAttribute("type", "win32"), new XAttribute("name", $"{assemblyName}.X"), @@ -44,14 +44,19 @@ public static void CreateManifestFromClsidmap(string assemblyName, string comHos foreach (JProperty property in clsidMap.Properties()) { - string guid = property.Name; - fileElement.Add(new XElement(ns + "comClass", new XAttribute("clsid", guid), new XAttribute("threadingModel", "Both"))); + string guidMaybe = property.Name; + Guid guid = Guid.Parse(guidMaybe); + fileElement.Add(new XElement(ns + "comClass", new XAttribute("clsid", guid.ToString("B")), new XAttribute("threadingModel", "Both"))); } manifest.Add(fileElement); XDocument manifestDocument = new XDocument(new XDeclaration("1.0", "UTF-8", "yes"), manifest); - using (XmlWriter manifestWriter = XmlWriter.Create(comManifestPath)) + XmlWriterSettings settings = new XmlWriterSettings() + { + Encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false) + }; + using (XmlWriter manifestWriter = XmlWriter.Create(comManifestPath, settings)) { manifestDocument.WriteTo(manifestWriter); } diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/ResolveAppHosts.cs b/src/Tasks/Microsoft.NET.Build.Tasks/ResolveAppHosts.cs index edd892804185..31872047ccab 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/ResolveAppHosts.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/ResolveAppHosts.cs @@ -19,6 +19,8 @@ public class ResolveAppHosts : TaskBase public string AppHostRuntimeIdentifier { get; set; } + public string[] OtherRuntimeIdentifiers { get; set; } + public string RuntimeFrameworkVersion { get; set; } public ITaskItem[] PackAsToolShimRuntimeIdentifiers { get; set; } = Array.Empty(); @@ -88,7 +90,8 @@ protected override void ExecuteCore() packagesToDownload, DotNetAppHostExecutableNameWithoutExtension, "AppHost", - isExecutable: true); + isExecutable: true, + errorIfNotFound: true); if (appHostItem != null) { @@ -101,7 +104,8 @@ protected override void ExecuteCore() packagesToDownload, DotNetComHostLibraryNameWithoutExtension, "ComHost", - isExecutable: false); + isExecutable: false, + errorIfNotFound: true); if (comHostItem != null) { @@ -120,7 +124,8 @@ protected override void ExecuteCore() packagesToDownload, DotNetAppHostExecutableNameWithoutExtension, "AppHost", - isExecutable: true); + isExecutable: true, + errorIfNotFound: true); if (appHostItem != null) { @@ -130,6 +135,26 @@ protected override void ExecuteCore() PackAsToolShimAppHostPacks = packAsToolShimAppHostPacks.ToArray(); } + if (OtherRuntimeIdentifiers != null) + { + foreach (var otherRuntimeIdentifier in OtherRuntimeIdentifiers) + { + // Download any apphost packages for other runtime identifiers. + // This allows you to specify the list of RIDs in RuntimeIdentifiers and only restore once, + // and then build for each RuntimeIdentifier without restoring separately. + + // We discard the return value, and pass in some bogus data that won't be used, because + // we won't use the assets from the apphost pack in this build. + GetHostItem(otherRuntimeIdentifier, + knownAppHostPacksForTargetFramework, + packagesToDownload, + hostNameWithoutExtension: "unused", + itemName: "unused", + isExecutable: true, + errorIfNotFound: false); + } + } + if (packagesToDownload.Any()) { PackagesToDownload = packagesToDownload.ToArray(); @@ -141,7 +166,8 @@ private ITaskItem GetHostItem(string runtimeIdentifier, List packagesToDownload, string hostNameWithoutExtension, string itemName, - bool isExecutable) + bool isExecutable, + bool errorIfNotFound) { var selectedAppHostPack = knownAppHostPacksForTargetFramework.Single(); @@ -165,12 +191,26 @@ private ITaskItem GetHostItem(string runtimeIdentifier, if (wasInGraph) { // NETSDK1084: There was no app host for available for the specified RuntimeIdentifier '{0}'. - Log.LogError(Strings.NoAppHostAvailable, runtimeIdentifier); + if (errorIfNotFound) + { + Log.LogError(Strings.NoAppHostAvailable, runtimeIdentifier); + } + else + { + Log.LogMessage(Strings.NoAppHostAvailable, runtimeIdentifier); + } } else { // NETSDK1083: The specified RuntimeIdentifier '{0}' is not recognized. - Log.LogError(Strings.RuntimeIdentifierNotRecognized, runtimeIdentifier); + if (errorIfNotFound) + { + Log.LogError(Strings.RuntimeIdentifierNotRecognized, runtimeIdentifier); + } + else + { + Log.LogMessage(Strings.RuntimeIdentifierNotRecognized, runtimeIdentifier); + } } return null; } diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/ResolveFrameworkReferences.cs b/src/Tasks/Microsoft.NET.Build.Tasks/ResolveFrameworkReferences.cs index 4a3c9028c792..0016504f3fda 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/ResolveFrameworkReferences.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/ResolveFrameworkReferences.cs @@ -113,7 +113,7 @@ protected override void ExecuteCore() string targetingPackPath = null; if (!string.IsNullOrEmpty(TargetingPackRoot)) { - targetingPackPath = Path.Combine(TargetingPackRoot, knownFrameworkReference.TargetingPackName, knownFrameworkReference.TargetingPackVersion); + targetingPackPath = Path.Combine(TargetingPackRoot, knownFrameworkReference.TargetingPackName, targetingPackVersion); } if (targetingPackPath != null && Directory.Exists(targetingPackPath)) { diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageAssets.cs b/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageAssets.cs index 5e379a798d22..d33a0f6ec7c7 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageAssets.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageAssets.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Security.Cryptography; using System.Text; +using Microsoft.Build.Evaluation; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; using NuGet.Common; @@ -1138,8 +1139,7 @@ private void WriteItem(string itemSpec) { FlushMetadata(); _itemCount++; - _writer.Write(itemSpec); - + _writer.Write(ProjectCollection.Escape(itemSpec)); } private void WriteItem(string itemSpec, LockFileTargetLibrary package) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/RunReadyToRunCompiler.cs b/src/Tasks/Microsoft.NET.Build.Tasks/RunReadyToRunCompiler.cs index 117f69f24b18..6d6430f22f2e 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/RunReadyToRunCompiler.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/RunReadyToRunCompiler.cs @@ -2,7 +2,11 @@ // 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.Reflection.Metadata; +using System.Reflection.PortableExecutable; +using System.Text; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; @@ -14,6 +18,8 @@ public class RunReadyToRunCompiler : ToolTask public ITaskItem CrossgenTool { get; set; } [Required] public ITaskItem CompilationEntry { get; set; } + [Required] + public ITaskItem[] ImplementationAssemblies { get; set; } private string _crossgenPath; private string _clrjitPath; @@ -22,7 +28,6 @@ public class RunReadyToRunCompiler : ToolTask private string _inputAssembly; private string _outputR2RImage; private string _outputPDBImage; - private string _platformAssembliesPaths; private string _createPDBCommand; private bool IsPdbCompilation => !String.IsNullOrEmpty(_createPDBCommand); @@ -48,7 +53,6 @@ protected override bool ValidateParameters() } _createPDBCommand = CompilationEntry.GetMetadata("CreatePDBCommand"); - _platformAssembliesPaths = CompilationEntry.GetMetadata("PlatformAssembliesPaths"); if (IsPdbCompilation) { @@ -80,18 +84,132 @@ protected override bool ValidateParameters() return true; } - protected override string GenerateCommandLineCommands() + // TEMP LOGIC - SDK Should provide correct list - When fixing https://github.com/dotnet/sdk/issues/3110, delete + // both IsManagedAssemblyToUseAsCrossgenReference and IsReferenceAssembly + bool IsManagedAssemblyToUseAsCrossgenReference(ITaskItem file) + { + // Reference only managed assemblies that will be published to the root directory. + string relativeOutputPath = file.GetMetadata(MetadataKeys.RelativePath); + if (!String.IsNullOrEmpty(Path.GetDirectoryName(relativeOutputPath))) + { + return false; + } + + using (FileStream fs = new FileStream(file.ItemSpec, FileMode.Open, FileAccess.Read)) + { + try + { + using (var pereader = new PEReader(fs)) + { + if (!pereader.HasMetadata) + return false; + + MetadataReader mdReader = pereader.GetMetadataReader(); + if (!mdReader.IsAssembly) + return false; + + // Reference assemblies should never be given to crossgen + if (IsReferenceAssembly(mdReader)) + return false; + } + } + catch (BadImageFormatException) + { + // Not a valid assembly file + return false; + } + } + + return true; + } + + private bool IsReferenceAssembly(MetadataReader mdReader) { + foreach (var attributeHandle in mdReader.GetAssemblyDefinition().GetCustomAttributes()) + { + StringHandle attributeTypeName = default; + StringHandle attributeTypeNamespace = default; + EntityHandle attributeCtor = mdReader.GetCustomAttribute(attributeHandle).Constructor; + + if (attributeCtor.Kind == HandleKind.MemberReference) + { + EntityHandle attributeMemberParent = mdReader.GetMemberReference((MemberReferenceHandle)attributeCtor).Parent; + if (attributeMemberParent.Kind == HandleKind.TypeReference) + { + TypeReference attributeTypeRef = mdReader.GetTypeReference((TypeReferenceHandle)attributeMemberParent); + attributeTypeName = attributeTypeRef.Name; + attributeTypeNamespace = attributeTypeRef.Namespace; + } + } + else if (attributeCtor.Kind == HandleKind.MethodDefinition) + { + TypeDefinitionHandle attributeTypeDefHandle = mdReader.GetMethodDefinition((MethodDefinitionHandle)attributeCtor).GetDeclaringType(); + TypeDefinition attributeTypeDef = mdReader.GetTypeDefinition(attributeTypeDefHandle); + attributeTypeName = attributeTypeDef.Name; + attributeTypeNamespace = attributeTypeDef.Namespace; + } + + if (!attributeTypeName.IsNil && + !attributeTypeNamespace.IsNil && + mdReader.StringComparer.Equals(attributeTypeName, "ReferenceAssemblyAttribute") && + mdReader.StringComparer.Equals(attributeTypeNamespace, "System.Runtime.CompilerServices")) + { + return true; + } + } + + return false; + } + + private string GetAssemblyReferencesCommands() + { + StringBuilder result = new StringBuilder(); + + // Add all runtime libraries to the list of references passed to crossgen + foreach (var runtimeAssembly in ImplementationAssemblies) + { + // When generating PDBs, we must not add a reference to the IL version of the R2R image for which we're trying to generate a PDB + if (IsPdbCompilation && String.Equals(Path.GetFileName(runtimeAssembly.ItemSpec), Path.GetFileName(_outputR2RImage), StringComparison.OrdinalIgnoreCase)) + continue; + + // TODO: Delete check when fixing https://github.com/dotnet/sdk/issues/3110 + if (!IsManagedAssemblyToUseAsCrossgenReference(runtimeAssembly)) + continue; + + result.AppendLine($"/r \"{runtimeAssembly}\""); + } + + return result.ToString(); + } + + protected override string GenerateResponseFileCommands() + { + StringBuilder result = new StringBuilder(); + + result.AppendLine("/nologo"); + if (IsPdbCompilation) { - return String.IsNullOrEmpty(_diasymreaderPath) ? - $"/nologo /Platform_Assemblies_Paths \"{_platformAssembliesPaths}\" {_createPDBCommand} \"{_outputR2RImage}\"" : - $"/nologo /Platform_Assemblies_Paths \"{_platformAssembliesPaths}\" /DiasymreaderPath \"{_diasymreaderPath}\" {_createPDBCommand} \"{_outputR2RImage}\""; + result.Append(GetAssemblyReferencesCommands()); + + if (!String.IsNullOrEmpty(_diasymreaderPath)) + { + result.AppendLine($"/DiasymreaderPath \"{_diasymreaderPath}\""); + } + + result.AppendLine(_createPDBCommand); + result.AppendLine($"\"{_outputR2RImage}\""); } else { - return $"/nologo /MissingDependenciesOK /JITPath \"{_clrjitPath}\" /Platform_Assemblies_Paths \"{_platformAssembliesPaths}\" /out \"{_outputR2RImage}\" \"{_inputAssembly}\""; + result.AppendLine("/MissingDependenciesOK"); + result.AppendLine($"/JITPath \"{_clrjitPath}\""); + result.Append(GetAssemblyReferencesCommands()); + result.AppendLine($"/out \"{_outputR2RImage}\""); + result.AppendLine($"\"{_inputAssembly}\""); } + + return result.ToString(); } protected override int ExecuteTool(string pathToTool, string responseFileCommands, string commandLineCommands) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.ILLink.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.ILLink.targets new file mode 100644 index 000000000000..bf6973b09d45 --- /dev/null +++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.ILLink.targets @@ -0,0 +1,120 @@ + + + + + + + $(IntermediateOutputPath)linked\ + $(IntermediateLinkDir)\ + + <_LinkSemaphore>$(IntermediateOutputPath)Link.semaphore + + new + + + + + + + + + + + + <_LinkedResolvedFileToPublish Include="@(_LinkedResolvedFileToPublishCandidates)" Condition="Exists('%(Identity)')" /> + + + + + + + <_RemovedManagedAssemblies Include="@(_ManagedAssembliesToLink)" Condition="!Exists('$(IntermediateLinkDir)%(Filename)%(Extension)')" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ManagedAssembliesToLink Remove="@(_ManagedResolvedFileToPublish->WithMetadataValue('AssetType', 'resources'))" /> + <_LinkedResolvedFileToPublishCandidates Include="@(_ManagedAssembliesToLink->'$(IntermediateLinkDir)%(Filename)%(Extension)')" /> + + + + + + diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets index 99ed2d7e03b6..e921a0f21fd8 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets +++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets @@ -48,6 +48,7 @@ Copyright (c) .NET Foundation. All rights reserved. PrepareForPublish; ComputeAndCopyFilesToPublishDirectory; GeneratePublishDependencyFile; + BundlePublishDirectory; @@ -85,6 +86,9 @@ Copyright (c) .NET Foundation. All rights reserved. --> + + $(PublishDir)\ @@ -103,6 +107,7 @@ Copyright (c) .NET Foundation. All rights reserved. --> @@ -111,6 +116,8 @@ Copyright (c) .NET Foundation. All rights reserved. CopyFilesToPublishDirectory Copy all build outputs, satellites and other necessary files to the publish directory. + When publishing to a single file, only those files that are not bundled are copied. + The remaining files are directly written to the bundle file. ============================================================ --> + + <_ResolvedUnbundledFileToPublishPreserveNewest + Include="@(_ResolvedFileToPublishPreserveNewest)" + Condition="'$(PublishSingleFile)' != 'true' or + '%(_ResolvedFileToPublishPreserveNewest.ExcludeFromSingleFile)'=='true'" /> + + - + + <_ResolvedUnbundledFileToPublishAlways + Include="@(_ResolvedFileToPublishAlways)" + Condition="'$(PublishSingleFile)' != 'true' or + '%(_ResolvedFileToPublishAlways.ExcludeFromSingleFile)'=='true'" /> + + - - + Condition="'$(_TargetFrameworkVersionWithoutV)' >= '3.0' And '$(PublishReadyToRun)' == 'true' And '$(TargetFrameworkIdentifier)' == '.NETCoreApp'" + DependsOnTargets="_PrepareForReadyToRunCompilation; + _CreateR2RImages; + _CreateR2RSymbols"> @@ -200,11 +219,8 @@ Copyright (c) .NET Foundation. All rights reserved. and do not replace them. IL PDBs are still required for debugging. Native PDBs emitted by the R2R compiler are only used for profiling purposes. --> - <_ResolvedFileToPublishAlways Remove="@(_ReadyToRunCompileListPublishAlways)" /> - <_ResolvedFileToPublishAlways Include="@(_ReadyToRunFilesToPublishAlways)" /> - - <_ResolvedFileToPublishPreserveNewest Remove="@(_ReadyToRunCompileListPreserveNewest)" /> - <_ResolvedFileToPublishPreserveNewest Include="@(_ReadyToRunFilesToPreserveNewest)" /> + + @@ -223,29 +239,26 @@ Copyright (c) .NET Foundation. All rights reserved. <_ReadyToRunOutputPath>$(IntermediateOutputPath)R2R + + + - + FilesToPublish="@(ResolvedFileToPublish)" + ExcludeList="@(PublishReadyToRunExclude)" + EmitSymbols="$(PublishReadyToRunEmitSymbols)"> - - + + - - - - - + @@ -253,94 +266,52 @@ Copyright (c) .NET Foundation. All rights reserved. - - - - - - - - <_ReadyToRunCompilationFailures Condition="'$(_ReadyToRunCompilerExitCode)' != '' And $(_ReadyToRunCompilerExitCode) != 0" - Include="@(_ReadyToRunCompileListPreserveNewest)" /> - - - - - + + <_ReadyToRunCompilationFailures Condition="'$(_ReadyToRunCompilerExitCode)' != '' And $(_ReadyToRunCompilerExitCode) != 0" - Include="@(_ReadyToRunSymbolsCompileListPreserveNewest)" /> + Include="@(_ReadyToRunCompileList)" /> - + + <_ReadyToRunCompilationFailures Condition="'$(_ReadyToRunCompilerExitCode)' != '' And $(_ReadyToRunCompilerExitCode) != 0" - Include="@(_ReadyToRunCompileListPublishAlways)" /> - - - - - - - - - - - - <_ReadyToRunCompilationFailures Condition="'$(_ReadyToRunCompilerExitCode)' != '' And $(_ReadyToRunCompilerExitCode) != 0" - Include="@(_ReadyToRunSymbolsCompileListPublishAlways)" /> + Include="@(_ReadyToRunSymbolsCompileList)" /> @@ -353,15 +324,15 @@ Copyright (c) .NET Foundation. All rights reserved. --> + <_ResolvedFileToPublishPreserveNewest Include="@(ResolvedFileToPublish)" - Condition="'%(ResolvedFileToPublish.CopyToPublishDirectory)'=='PreserveNewest'" /> + Condition="'%(ResolvedFileToPublish.CopyToPublishDirectory)'=='PreserveNewest'" /> <_ResolvedFileToPublishAlways Include="@(ResolvedFileToPublish)" - Condition="'%(ResolvedFileToPublish.CopyToPublishDirectory)'=='Always'" /> + Condition="'%(ResolvedFileToPublish.CopyToPublishDirectory)'=='Always'" /> - @@ -625,7 +597,7 @@ Copyright (c) .NET Foundation. All rights reserved. a non-empty value and the original behavior will be restored. --> <_GCTPDIKeepDuplicates>false - <_GCTPDIKeepMetadata>CopyToPublishDirectory;TargetPath + <_GCTPDIKeepMetadata>CopyToPublishDirectory;ExcludeFromSingleFile;TargetPath @@ -761,15 +733,55 @@ Copyright (c) .NET Foundation. All rights reserved. DependsOnTargets="_ComputeExcludeFromPublishPackageReferences; _ParseTargetManifestFiles"> - + <_UseBuildDependencyFile Condition="'@(_ExcludeFromPublishPackageReference)' == '' and '@(RuntimeStorePackages)' == '' and - '$(PreserveStoreLayout)' != 'true'">true + '$(PreserveStoreLayout)' != 'true' and + '$(PublishTrimmed)' != 'true'">true + + + + + <_FilesToBundle Include="@(_ResolvedFileToPublishPreserveNewest)" + Condition="'%(_ResolvedFileToPublishPreserveNewest.ExcludeFromSingleFile)' != 'true'"/> + <_FilesToBundle Include="@(_ResolvedFileToPublishAlways)" + Condition="'%(_ResolvedFileToPublishPreserveNewest.ExcludeFromSingleFile)' != 'true'"/> + + + + + + + + + false + + + + + + + + + $(PublishItemsOutputGroupDependsOn); + ComputeFilesToPublish; + + + + + + + + + $(PackageOutputPath)tests\ + + $(MSBuildThisFileDirectory)Common\runtimeconfig.template.json diff --git a/src/Tests/Microsoft.NET.Build.Tests/AppHostTests.cs b/src/Tests/Microsoft.NET.Build.Tests/AppHostTests.cs new file mode 100644 index 000000000000..0bd860953319 --- /dev/null +++ b/src/Tests/Microsoft.NET.Build.Tests/AppHostTests.cs @@ -0,0 +1,235 @@ +// 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.Linq; +using System.Reflection.PortableExecutable; +using FluentAssertions; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.NET.TestFramework; +using Microsoft.NET.TestFramework.Assertions; +using Microsoft.NET.TestFramework.Commands; +using Microsoft.NET.TestFramework.ProjectConstruction; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.NET.Build.Tests +{ + public class AppHostTests : SdkTest + { + public AppHostTests(ITestOutputHelper log) : base(log) + { + } + + [Theory] + [InlineData("netcoreapp3.0")] + public void It_builds_a_runnable_apphost_by_default(string targetFramework) + { + var testAsset = _testAssetsManager + .CopyTestAsset("HelloWorld", identifier: targetFramework) + .WithSource() + .WithTargetFramework(targetFramework); + + var buildCommand = new BuildCommand(Log, testAsset.TestRoot); + buildCommand + .Execute(new string[] { + "/restore", + }) + .Should() + .Pass(); + + var outputDirectory = buildCommand.GetOutputDirectory(targetFramework); + var hostExecutable = $"HelloWorld{Constants.ExeSuffix}"; + + outputDirectory.Should().OnlyHaveFiles(new[] { + hostExecutable, + "HelloWorld.dll", + "HelloWorld.pdb", + "HelloWorld.deps.json", + "HelloWorld.runtimeconfig.dev.json", + "HelloWorld.runtimeconfig.json", + }); + + Command.Create(Path.Combine(outputDirectory.FullName, hostExecutable), new string[] { }) + .EnvironmentVariable( + Environment.Is64BitProcess ? "DOTNET_ROOT" : "DOTNET_ROOT(x86)", + Path.GetDirectoryName(TestContext.Current.ToolsetUnderTest.DotNetHostPath)) + .CaptureStdOut() + .Execute() + .Should() + .Pass() + .And + .HaveStdOutContaining("Hello World!"); + } + + [Theory] + [InlineData("netcoreapp2.1")] + [InlineData("netcoreapp2.2")] + public void It_does_not_build_with_an_apphost_by_default_before_netcoreapp_3(string targetFramework) + { + var testAsset = _testAssetsManager + .CopyTestAsset("HelloWorld", identifier: targetFramework) + .WithSource() + .WithTargetFramework(targetFramework); + + var buildCommand = new BuildCommand(Log, testAsset.TestRoot); + buildCommand + .Execute(new string[] { "/restore" }) + .Should() + .Pass(); + + var outputDirectory = buildCommand.GetOutputDirectory(targetFramework); + + outputDirectory.Should().OnlyHaveFiles(new[] { + "HelloWorld.dll", + "HelloWorld.pdb", + "HelloWorld.deps.json", + "HelloWorld.runtimeconfig.dev.json", + "HelloWorld.runtimeconfig.json", + }); + } + + [WindowsOnlyTheory] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("AnyCPU")] + [InlineData("")] + public void It_uses_an_apphost_based_on_platform_target(string target) + { + var targetFramework = "netcoreapp3.0"; + + var testAsset = _testAssetsManager + .CopyTestAsset("HelloWorld") + .WithSource(); + + var buildCommand = new BuildCommand(Log, testAsset.TestRoot); + buildCommand + .Execute(new string[] { + "/restore", + $"/p:TargetFramework={targetFramework}", + $"/p:PlatformTarget={target}", + $"/p:NETCoreSdkRuntimeIdentifier={EnvironmentInfo.GetCompatibleRid(targetFramework)}" + }) + .Should() + .Pass(); + + var apphostPath = Path.Combine(buildCommand.GetOutputDirectory(targetFramework).FullName, "HelloWorld.exe"); + if (target == "x86") + { + IsPE32(apphostPath).Should().BeTrue(); + } + else if (target == "x64") + { + IsPE32(apphostPath).Should().BeFalse(); + } + else + { + IsPE32(apphostPath).Should().Be(!Environment.Is64BitProcess); + } + } + + [WindowsOnlyFact] + public void AppHost_contains_resources_from_the_managed_dll() + { + var targetFramework = "netcoreapp2.0"; + var runtimeIdentifier = EnvironmentInfo.GetCompatibleRid(targetFramework); + + var version = "5.6.7.8"; + var testProject = new TestProject() + { + Name = "ResourceTest", + TargetFrameworks = targetFramework, + RuntimeIdentifier = runtimeIdentifier, + IsSdkProject = true, + IsExe = true, + }; + testProject.AdditionalProperties.Add("AssemblyVersion", version); + + var testAsset = _testAssetsManager.CreateTestProject(testProject) + .Restore(Log, testProject.Name); + + var buildCommand = new BuildCommand(Log, Path.Combine(testAsset.TestRoot, testProject.Name)); + + buildCommand.Execute() + .Should() + .Pass(); + + var outputDirectory = buildCommand.GetOutputDirectory(targetFramework, runtimeIdentifier: runtimeIdentifier); + outputDirectory.Should().HaveFiles(new[] { testProject.Name + ".exe" }); + + string apphostPath = Path.Combine(outputDirectory.FullName, testProject.Name + ".exe"); + var apphostVersion = FileVersionInfo.GetVersionInfo(apphostPath).FileVersion; + apphostVersion.Should().Be(version); + } + + [WindowsOnlyFact] + public void FSharp_app_can_customize_the_apphost() + { + var targetFramework = "netcoreapp3.0"; + var testAsset = _testAssetsManager + .CopyTestAsset("HelloWorldFS") + .WithSource() + .WithProjectChanges(project => + { + var ns = project.Root.Name.Namespace; + var propertyGroup = project.Root.Elements(ns + "PropertyGroup").First(); + propertyGroup.Element(ns + "TargetFramework").SetValue(targetFramework); + }) + .Restore(Log); + + var buildCommand = new BuildCommand(Log, testAsset.TestRoot); + buildCommand + .Execute("/p:CopyLocalLockFileAssemblies=false") + .Should() + .Pass(); + + var outputDirectory = buildCommand.GetOutputDirectory(targetFramework); + + outputDirectory.Should().OnlyHaveFiles(new[] { + "TestApp.deps.json", + "TestApp.dll", + "TestApp.exe", + "TestApp.pdb", + "TestApp.runtimeconfig.dev.json", + "TestApp.runtimeconfig.json", + }); + } + + [Fact] + public void If_UseAppHost_is_false_it_does_not_try_to_find_an_AppHost() + { + var testProject = new TestProject() + { + Name = "NoAppHost", + TargetFrameworks = "netcoreapp3.0", + // Use "any" as RID so that it will fail to find AppHost + RuntimeIdentifier = "any", + IsSdkProject = true, + IsExe = true, + }; + testProject.AdditionalProperties["SelfContained"] = "false"; + testProject.AdditionalProperties["UseAppHost"] = "false"; + + var testAsset = _testAssetsManager.CreateTestProject(testProject) + .Restore(Log, testProject.Name); + + var buildCommand = new BuildCommand(Log, testAsset.TestRoot, testProject.Name); + + buildCommand.Execute() + .Should() + .Pass(); + + } + + private static bool IsPE32(string path) + { + using (var reader = new PEReader(File.OpenRead(path))) + { + return reader.PEHeaders.PEHeader.Magic == PEMagic.PE32; + } + } + + } +} diff --git a/src/Tests/Microsoft.NET.Build.Tests/DepsFileSkipTests.cs b/src/Tests/Microsoft.NET.Build.Tests/DepsFileSkipTests.cs index 5189f3878739..2db5d5e61be6 100644 --- a/src/Tests/Microsoft.NET.Build.Tests/DepsFileSkipTests.cs +++ b/src/Tests/Microsoft.NET.Build.Tests/DepsFileSkipTests.cs @@ -134,8 +134,6 @@ public void ResourceAssetFromPackageCanBeSkipped() string filenameNotToSkip = "es/Humanizer.resources.dll"; string assetType = "resources"; - testProject.AdditionalProperties["DepsFileGenerationMode"] = "new"; - var testAsset = _testAssetsManager.CreateTestProject(testProject, testProject.Name) .WithProjectChanges(project => AddSkipTarget(project, filenameToSkip)) .Restore(Log, testProject.Name); @@ -177,8 +175,6 @@ public void ResourceAssetFromPackageCanBeSkipped() private void TestSkippingFile(TestProject testProject, string filenameToSkip, string assetType) { - testProject.AdditionalProperties["DepsFileGenerationMode"] = "new"; - var testAsset = _testAssetsManager.CreateTestProject(testProject, testProject.Name) .WithProjectChanges(project => AddSkipTarget(project, filenameToSkip)) .Restore(Log, testProject.Name); diff --git a/src/Tests/Microsoft.NET.Build.Tests/GivenFrameworkReferences.cs b/src/Tests/Microsoft.NET.Build.Tests/GivenFrameworkReferences.cs index c4203345062a..73902c8e3026 100644 --- a/src/Tests/Microsoft.NET.Build.Tests/GivenFrameworkReferences.cs +++ b/src/Tests/Microsoft.NET.Build.Tests/GivenFrameworkReferences.cs @@ -22,7 +22,9 @@ public GivenFrameworkReferences(ITestOutputHelper log) : base(log) { } - [WindowsOnlyFact] + // Tests in this class are currently Core MSBuild only, as they check for PackageDownload items, + // which are currently only used in Core MSBuild + [CoreMSBuildAndWindowsOnlyFact] public void Multiple_frameworks_are_written_to_runtimeconfig_when_there_are_multiple_FrameworkReferences() { var testProject = new TestProject() @@ -84,7 +86,7 @@ public static void Main(string [] args) runtimeFrameworkNames.Should().BeEquivalentTo("Microsoft.AspNetCore.App", "Microsoft.WindowsDesktop.App"); } - [Fact] + [CoreMSBuildOnlyFact] public void The_build_fails_when_there_is_an_unknown_FrameworkReference() { var testProject = new TestProject() @@ -123,7 +125,7 @@ public void The_build_fails_when_there_is_an_unknown_FrameworkReference() ; } - [Theory] + [CoreMSBuildOnlyTheory] [InlineData("netcoreapp2.1", false)] [InlineData("netcoreapp3.0", true)] public void KnownFrameworkReferencesOnlyApplyToCorrectTargetFramework(string targetFramework, bool shouldPass) @@ -166,7 +168,7 @@ public void KnownFrameworkReferencesOnlyApplyToCorrectTargetFramework(string tar .And.HaveStdOutContaining("Microsoft.AspNetCore.App"); } } - [Fact] + [CoreMSBuildOnlyFact] public void TargetingPackDownloadCanBeDisabled() { var testProject = new TestProject() @@ -203,7 +205,7 @@ public void TargetingPackDownloadCanBeDisabled() .HaveStdOutContaining("NETSDK1073"); } - [Fact] + [CoreMSBuildOnlyFact] public void BuildFailsIfRuntimePackIsNotAvailableForRuntimeIdentifier() { var testProject = new TestProject() @@ -242,7 +244,7 @@ public void BuildFailsIfRuntimePackIsNotAvailableForRuntimeIdentifier() .HaveStdOutContaining("1 Error(s)"); } - [Fact] + [CoreMSBuildOnlyFact] public void BuildFailsIfInvalidRuntimeIdentifierIsSpecified() { var testProject = new TestProject() @@ -269,7 +271,7 @@ public void BuildFailsIfInvalidRuntimeIdentifierIsSpecified() .HaveStdOutContaining("1 Error(s)"); } - [Fact] + [CoreMSBuildOnlyFact] public void BuildFailsIfRuntimePackHasNotBeenRestored() { var testProject = new TestProject() @@ -310,7 +312,7 @@ public void BuildFailsIfRuntimePackHasNotBeenRestored() } - [Fact] + [CoreMSBuildOnlyFact] public void RuntimeFrameworkVersionCanBeSpecifiedOnFrameworkReference() { var testProject = new TestProject(); @@ -342,7 +344,7 @@ public void RuntimeFrameworkVersionCanBeSpecifiedOnFrameworkReference() resolvedVersions.AppHostPack["AppHost"].Should().Be("3.0.0-runtimeframeworkversion-property"); } - [Fact] + [CoreMSBuildOnlyFact] public void RuntimeFrameworkVersionCanBeSpecifiedViaProperty() { var testProject = new TestProject(); @@ -365,7 +367,7 @@ public void RuntimeFrameworkVersionCanBeSpecifiedViaProperty() resolvedVersions.AppHostPack["AppHost"].Should().Be(runtimeFrameworkVersion); } - [Theory] + [CoreMSBuildOnlyTheory] [InlineData(true)] [InlineData(false)] public void TargetLatestPatchCanBeSpecifiedOnFrameworkReference(bool attributeValue) @@ -401,7 +403,7 @@ public void TargetLatestPatchCanBeSpecifiedOnFrameworkReference(bool attributeVa resolvedVersions.AppHostPack["AppHost"].Should().Be("3.0.0-apphostversion"); } - [Theory] + [CoreMSBuildOnlyTheory] [InlineData(true)] [InlineData(false)] public void TargetLatestPatchCanBeSpecifiedViaProperty(bool propertyValue) @@ -427,7 +429,7 @@ public void TargetLatestPatchCanBeSpecifiedViaProperty(bool propertyValue) resolvedVersions.AppHostPack["AppHost"].Should().Be("3.0.0-apphostversion"); } - [Fact] + [CoreMSBuildOnlyFact] public void TargetingPackVersionCanBeSpecifiedOnFrameworkReference() { var testProject = new TestProject(); @@ -499,7 +501,7 @@ private ResolvedVersionInfo GetResolvedVersions(TestProject testProject, - + @@ -558,7 +560,9 @@ public static ResolvedVersionInfo ParseFrom(string path) dict = versionInfo.RuntimeFramework; break; case "PackageDownload": + // PackageDownload versions are enclosed in [brackets] dict = versionInfo.PackageDownload; + version = version.Substring(1, version.Length - 2); break; case "TargetingPack": dict = versionInfo.TargetingPack; diff --git a/src/Tests/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildADesktopExeWithFSharp.cs b/src/Tests/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildADesktopExeWithFSharp.cs index 4c5491b4f0a4..be90dd73fe39 100644 --- a/src/Tests/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildADesktopExeWithFSharp.cs +++ b/src/Tests/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildADesktopExeWithFSharp.cs @@ -58,38 +58,5 @@ public void It_builds_a_simple_desktop_app() "System.ValueTuple.dll", }); } - - [WindowsOnlyFact] - public void It_can_customize_the_apphost() - { - var targetFramework = "netcoreapp3.0"; - var testAsset = _testAssetsManager - .CopyTestAsset("HelloWorldFS") - .WithSource() - .WithProjectChanges(project => - { - var ns = project.Root.Name.Namespace; - var propertyGroup = project.Root.Elements(ns + "PropertyGroup").First(); - propertyGroup.Element(ns + "TargetFramework").SetValue(targetFramework); - }) - .Restore(Log); - - var buildCommand = new BuildCommand(Log, testAsset.TestRoot); - buildCommand - .Execute("/p:CopyLocalLockFileAssemblies=false") - .Should() - .Pass(); - - var outputDirectory = buildCommand.GetOutputDirectory(targetFramework); - - outputDirectory.Should().OnlyHaveFiles(new[] { - "TestApp.deps.json", - "TestApp.dll", - "TestApp.exe", - "TestApp.pdb", - "TestApp.runtimeconfig.dev.json", - "TestApp.runtimeconfig.json", - }); - } } } diff --git a/src/Tests/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildANetCoreApp.cs b/src/Tests/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildANetCoreApp.cs index 1f1c1d6cbc83..b4940f269373 100644 --- a/src/Tests/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildANetCoreApp.cs +++ b/src/Tests/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildANetCoreApp.cs @@ -253,113 +253,6 @@ public void It_restores_only_ridless_tfm() targetDefs.Should().Contain(".NETCoreApp,Version=v1.1"); } - [Theory] - [InlineData("netcoreapp3.0")] - public void It_builds_a_runnable_apphost_by_default(string targetFramework) - { - var testAsset = _testAssetsManager - .CopyTestAsset("HelloWorld", identifier: targetFramework) - .WithSource() - .WithTargetFramework(targetFramework); - - var buildCommand = new BuildCommand(Log, testAsset.TestRoot); - buildCommand - .Execute(new string[] { - "/restore", - }) - .Should() - .Pass(); - - var outputDirectory = buildCommand.GetOutputDirectory(targetFramework); - var hostExecutable = $"HelloWorld{Constants.ExeSuffix}"; - - outputDirectory.Should().OnlyHaveFiles(new[] { - hostExecutable, - "HelloWorld.dll", - "HelloWorld.pdb", - "HelloWorld.deps.json", - "HelloWorld.runtimeconfig.dev.json", - "HelloWorld.runtimeconfig.json", - }); - - Command.Create(Path.Combine(outputDirectory.FullName, hostExecutable), new string[] {}) - .EnvironmentVariable( - Environment.Is64BitProcess ? "DOTNET_ROOT" : "DOTNET_ROOT(x86)", - Path.GetDirectoryName(TestContext.Current.ToolsetUnderTest.DotNetHostPath)) - .CaptureStdOut() - .Execute() - .Should() - .Pass() - .And - .HaveStdOutContaining("Hello World!"); - } - - [Theory] - [InlineData("netcoreapp2.1")] - [InlineData("netcoreapp2.2")] - public void It_does_not_build_with_an_apphost_by_default_before_netcoreapp_3(string targetFramework) - { - var testAsset = _testAssetsManager - .CopyTestAsset("HelloWorld", identifier: targetFramework) - .WithSource() - .WithTargetFramework(targetFramework); - - var buildCommand = new BuildCommand(Log, testAsset.TestRoot); - buildCommand - .Execute(new string[] { "/restore" }) - .Should() - .Pass(); - - var outputDirectory = buildCommand.GetOutputDirectory(targetFramework); - - outputDirectory.Should().OnlyHaveFiles(new[] { - "HelloWorld.dll", - "HelloWorld.pdb", - "HelloWorld.deps.json", - "HelloWorld.runtimeconfig.dev.json", - "HelloWorld.runtimeconfig.json", - }); - } - - [WindowsOnlyTheory] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("AnyCPU")] - [InlineData("")] - public void It_uses_an_apphost_based_on_platform_target(string target) - { - var targetFramework = "netcoreapp3.0"; - - var testAsset = _testAssetsManager - .CopyTestAsset("HelloWorld") - .WithSource(); - - var buildCommand = new BuildCommand(Log, testAsset.TestRoot); - buildCommand - .Execute(new string[] { - "/restore", - $"/p:TargetFramework={targetFramework}", - $"/p:PlatformTarget={target}", - $"/p:NETCoreSdkRuntimeIdentifier={EnvironmentInfo.GetCompatibleRid(targetFramework)}" - }) - .Should() - .Pass(); - - var apphostPath = Path.Combine(buildCommand.GetOutputDirectory(targetFramework).FullName, "HelloWorld.exe"); - if (target == "x86") - { - IsPE32(apphostPath).Should().BeTrue(); - } - else if (target == "x64") - { - IsPE32(apphostPath).Should().BeFalse(); - } - else - { - IsPE32(apphostPath).Should().Be(!Environment.Is64BitProcess); - } - } - [Theory] [InlineData("netcoreapp2.0")] [InlineData("netcoreapp2.1")] @@ -673,12 +566,55 @@ public void BuildWithTransitiveReferenceToNetCoreAppPackage() .Pass(); } - private static bool IsPE32(string path) + [WindowsOnlyFact] + public void It_escapes_resolved_package_assets_paths() { - using (var reader = new PEReader(File.OpenRead(path))) + var testProject = new TestProject() { - return reader.PEHeaders.PEHeader.Magic == PEMagic.PE32; - } + Name = "ProjectWithPackageThatNeedsEscapes", + TargetFrameworks = "net462", + IsSdkProject = true, + IsExe = true, + }; + + testProject.SourceFiles["ExampleReader.cs"] = @" +using System; +using System.Threading.Tasks; + +namespace ContentFilesExample +{ + internal static class ExampleInternals + { + internal static Task GetFileText(string fileName) + { + throw new NotImplementedException(); + } + } +} + +class Program +{ + static void Main(string[] args) + { + Console.WriteLine(""Hello World!""); + } +}"; + + // ContentFilesExample is an existing package that demonstrates the problem. + // It contains assets with paths that have '%2B', which MSBuild will unescape to '+'. + // Without the change to escape the asset paths, the asset will not be found inside the package. + testProject.PackageReferences.Add(new TestPackageReference("ContentFilesExample", "1.0.2")); + + var testAsset = _testAssetsManager + .CreateTestProject(testProject) + .Restore(Log, testProject.Name); + + var buildCommand = new BuildCommand(Log, Path.Combine(testAsset.TestRoot, testProject.Name)); + + buildCommand + .Execute() + .Should() + .Pass(); } } } diff --git a/src/Tests/Microsoft.NET.Build.Tests/GivenThatWeWantToCustomizeTheApphost.cs b/src/Tests/Microsoft.NET.Build.Tests/GivenThatWeWantToCustomizeTheApphost.cs deleted file mode 100644 index 54ef21a1e016..000000000000 --- a/src/Tests/Microsoft.NET.Build.Tests/GivenThatWeWantToCustomizeTheApphost.cs +++ /dev/null @@ -1,56 +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. - -using System.Diagnostics; -using System.IO; -using FluentAssertions; -using Microsoft.NET.TestFramework; -using Microsoft.NET.TestFramework.Assertions; -using Microsoft.NET.TestFramework.Commands; -using Microsoft.NET.TestFramework.ProjectConstruction; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.NET.Build.Tests -{ - public class GivenThatWeWantToCustomizeTheApphost : SdkTest - { - public GivenThatWeWantToCustomizeTheApphost(ITestOutputHelper log) : base(log) - { - } - - [WindowsOnlyFact] - public void It_contains_resources_from_the_managed_dll() - { - var targetFramework = "netcoreapp2.0"; - var runtimeIdentifier = EnvironmentInfo.GetCompatibleRid(targetFramework); - - var version = "5.6.7.8"; - var testProject = new TestProject() - { - Name = "ResourceTest", - TargetFrameworks = targetFramework, - RuntimeIdentifier = runtimeIdentifier, - IsSdkProject = true, - IsExe = true, - }; - testProject.AdditionalProperties.Add("AssemblyVersion", version); - - var testAsset = _testAssetsManager.CreateTestProject(testProject) - .Restore(Log, testProject.Name); - - var buildCommand = new BuildCommand(Log, Path.Combine(testAsset.TestRoot, testProject.Name)); - - buildCommand.Execute() - .Should() - .Pass(); - - var outputDirectory = buildCommand.GetOutputDirectory(targetFramework, runtimeIdentifier: runtimeIdentifier); - outputDirectory.Should().HaveFiles(new[] { testProject.Name + ".exe" }); - - string apphostPath = Path.Combine(outputDirectory.FullName, testProject.Name + ".exe"); - var apphostVersion = FileVersionInfo.GetVersionInfo(apphostPath).FileVersion; - apphostVersion.Should().Be(version); - } - } -} diff --git a/src/Tests/Microsoft.NET.Build.Tests/GivenThatWeWantToFilterSatelliteAssemblies.cs b/src/Tests/Microsoft.NET.Build.Tests/GivenThatWeWantToFilterSatelliteAssemblies.cs index 8516d2ae17ce..9e4f16e3fe38 100644 --- a/src/Tests/Microsoft.NET.Build.Tests/GivenThatWeWantToFilterSatelliteAssemblies.cs +++ b/src/Tests/Microsoft.NET.Build.Tests/GivenThatWeWantToFilterSatelliteAssemblies.cs @@ -46,10 +46,6 @@ public void It_only_publish_selected_ResourceLanguages(string targetFramework, b testProject.AdditionalProperties.Add("CopyLocalLockFileAssemblies", "true"); } - // Old deps file generation code still included all satellite languages in deps.json, - // so don't compare both versions - testProject.AdditionalProperties["DepsFileGenerationMode"] = "new"; - var testProjectInstance = _testAssetsManager.CreateTestProject(testProject, identifier: targetFramework) .Restore(Log, testProject.Name); diff --git a/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToFilterSatelliteAssemblies.cs b/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToFilterSatelliteAssemblies.cs index bd4f0b6d86e5..aec7cfa01f59 100644 --- a/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToFilterSatelliteAssemblies.cs +++ b/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToFilterSatelliteAssemblies.cs @@ -35,10 +35,6 @@ public void It_only_publishes_selected_ResourceLanguages() testProject.PackageReferences.Add(new TestPackageReference("System.Spatial", "5.8.3")); testProject.AdditionalProperties.Add("SatelliteResourceLanguages", "en-US;it;fr"); - // Old deps file generation code still included all satellite languages in deps.json, - // so don't compare both versions - testProject.AdditionalProperties["DepsFileGenerationMode"] = "new"; - var testProjectInstance = _testAssetsManager.CreateTestProject(testProject) .Restore(Log, testProject.Name); @@ -70,10 +66,6 @@ public void It_publishes_all_satellites_when_not_filtered() IsSdkProject = true }; - // Old deps file generation code still included all satellite languages in deps.json, - // so don't compare both versions - testProject.AdditionalProperties["DepsFileGenerationMode"] = "new"; - testProject.PackageReferences.Add(new TestPackageReference("System.Spatial", "5.8.3")); var testProjectInstance = _testAssetsManager.CreateTestProject(testProject) diff --git a/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishASingleFileApp.cs b/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishASingleFileApp.cs new file mode 100644 index 000000000000..7d75f70cef40 --- /dev/null +++ b/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishASingleFileApp.cs @@ -0,0 +1,199 @@ +// 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 FluentAssertions; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.PlatformAbstractions; +using Microsoft.NET.Build.Tasks; +using Microsoft.NET.TestFramework; +using Microsoft.NET.TestFramework.Assertions; +using Microsoft.NET.TestFramework.Commands; +using Microsoft.NET.TestFramework.ProjectConstruction; +using Xunit; +using Xunit.Abstractions; +using System; +using System.IO; + +namespace Microsoft.NET.Publish.Tests +{ + public class GivenThatWeWantToPublishASingleFileApp : SdkTest + { + private const string TestProjectName = "HelloWorldWithSubDirs"; + + private const string PublishSingleFile = "/p:PublishSingleFile=true"; + private const string FrameworkDependent = "/p:SelfContained=false"; + private const string IncludePdb = "/p:IncludeSymbolsInSingleFile=true"; + private const string ExcludeContent = "/p:ExcludeContent=true"; + private const string DontUseAppHost = "/p:UseAppHost=false"; + private const string ReadyToRun = "/p:PublishReadyToRun=true"; + + private readonly string RuntimeIdentifier = $"/p:RuntimeIdentifier={RuntimeEnvironment.GetRuntimeIdentifier()}"; + private readonly string SingleFile = $"{TestProjectName}{Constants.ExeSuffix}"; + private readonly string PdbFile = $"{TestProjectName}.pdb"; + private const string ContentFile = "Signature.stamp"; + + public GivenThatWeWantToPublishASingleFileApp(ITestOutputHelper log) : base(log) + { + } + + private PublishCommand GetPublishCommand() + { + var testAsset = _testAssetsManager + .CopyTestAsset(TestProjectName) + .WithSource(); + testAsset.Restore(Log, testAsset.TestRoot, RuntimeIdentifier); + + return new PublishCommand(Log, testAsset.TestRoot); + } + + private DirectoryInfo GetPublishDirectory(PublishCommand publishCommand) + { + return publishCommand.GetOutputDirectory(targetFramework: "netcoreapp3.0", + runtimeIdentifier: RuntimeEnvironment.GetRuntimeIdentifier()); + } + + [Fact] + public void It_errors_when_publishing_single_file_app_without_rid() + { + GetPublishCommand() + .Execute(PublishSingleFile) + .Should() + .Fail() + .And + .HaveStdOutContaining(Strings.CannotHaveSingleFileWithoutRuntimeIdentifier); + } + + [Fact] + public void It_errors_when_publishing_single_file_without_apphost() + { + GetPublishCommand() + .Execute(PublishSingleFile, RuntimeIdentifier, FrameworkDependent, DontUseAppHost) + .Should() + .Fail() + .And + .HaveStdOutContaining(Strings.CannotHaveSingleFileWithoutAppHost); + } + + [Fact] + public void It_errors_when_publishing_single_file_lib() + { + var testProject = new TestProject() + { + Name = "SingleFileClassLib", + TargetFrameworks = "netstandard2.0", + IsSdkProject = true, + IsExe = false, + }; + + var testAsset = _testAssetsManager.CreateTestProject(testProject) + .Restore(Log, testProject.Name, RuntimeIdentifier); + + var publishCommand = new PublishCommand(Log, Path.Combine(testAsset.TestRoot, testProject.Name)); + + publishCommand.Execute(PublishSingleFile, RuntimeIdentifier) + .Should() + .Fail() + .And + .HaveStdOutContaining(Strings.CannotHaveSingleFileWithoutExecutable); + } + + [Fact] + public void It_generates_a_single_file_for_framework_dependent_apps() + { + var publishCommand = GetPublishCommand(); + publishCommand + .Execute(PublishSingleFile, RuntimeIdentifier, FrameworkDependent) + .Should() + .Pass(); + + string[] expectedFiles = { SingleFile, PdbFile }; + GetPublishDirectory(publishCommand) + .Should() + .OnlyHaveFiles(expectedFiles); + } + + [Fact] + public void It_generates_a_single_file_for_self_contained_apps() + { + var publishCommand = GetPublishCommand(); + publishCommand + .Execute(PublishSingleFile, RuntimeIdentifier) + .Should() + .Pass(); + + string[] expectedFiles = { SingleFile, PdbFile }; + GetPublishDirectory(publishCommand) + .Should() + .OnlyHaveFiles(expectedFiles); + } + + [Fact] + public void It_generates_a_single_file_including_pdbs() + { + var publishCommand = GetPublishCommand(); + publishCommand + .Execute(PublishSingleFile, RuntimeIdentifier, IncludePdb) + .Should() + .Pass(); + + string[] expectedFiles = { SingleFile }; + GetPublishDirectory(publishCommand) + .Should() + .OnlyHaveFiles(expectedFiles); + } + + [Fact] + public void It_generates_a_single_file_excluding_content() + { + var publishCommand = GetPublishCommand(); + publishCommand + .Execute(PublishSingleFile, RuntimeIdentifier, ExcludeContent) + .Should() + .Pass(); + + string[] expectedFiles = { SingleFile, PdbFile, ContentFile }; + GetPublishDirectory(publishCommand) + .Should() + .OnlyHaveFiles(expectedFiles); + } + + [Fact] + public void It_generates_a_single_file_for_R2R_compiled_Apps() + { + var publishCommand = GetPublishCommand(); + publishCommand + .Execute(PublishSingleFile, RuntimeIdentifier, ReadyToRun) + .Should() + .Pass(); + + string[] expectedFiles = { SingleFile, PdbFile }; + GetPublishDirectory(publishCommand) + .Should() + .OnlyHaveFiles(expectedFiles); + } + + [Fact] + public void It_does_not_rewrite_the_single_file_unnecessarily() + { + var publishCommand = GetPublishCommand(); + var singleFilePath = Path.Combine(GetPublishDirectory(publishCommand).FullName, SingleFile); + + publishCommand + .Execute(PublishSingleFile, RuntimeIdentifier, FrameworkDependent) + .Should() + .Pass(); + DateTime fileWriteTimeAfterFirstRun = File.GetLastWriteTimeUtc(singleFilePath); + + WaitForUtcNowToAdvance(); + + publishCommand + .Execute(PublishSingleFile, RuntimeIdentifier, FrameworkDependent) + .Should() + .Pass(); + DateTime fileWriteTimeAfterSecondRun = File.GetLastWriteTimeUtc(singleFilePath); + + fileWriteTimeAfterSecondRun.Should().Be(fileWriteTimeAfterFirstRun); + } + + } +} diff --git a/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToRunCrossgen.cs b/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToRunCrossgen.cs index 32ac902bbeb5..14d55d1c21bc 100644 --- a/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToRunCrossgen.cs +++ b/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToRunCrossgen.cs @@ -56,8 +56,8 @@ public void It_creates_readytorun_images_for_all_assemblies_except_excluded_ones projectName, "ClassLib"); - testProject.AdditionalProperties["ReadyToRun"] = "True"; - testProject.AdditionalItems["ReadyToRunExclude"] = "Classlib.dll"; + testProject.AdditionalProperties["PublishReadyToRun"] = "True"; + testProject.AdditionalItems["PublishReadyToRunExclude"] = "Classlib.dll"; var testProjectInstance = _testAssetsManager.CreateTestProject(testProject) .Restore(Log, testProject.Name); @@ -96,8 +96,8 @@ public void It_creates_readytorun_symbols_when_switch_is_used(string targetFrame projectName, "ClassLib"); - testProject.AdditionalProperties["ReadyToRun"] = "True"; - testProject.AdditionalProperties["ReadyToRunEmitSymbols"] = "True"; + testProject.AdditionalProperties["PublishReadyToRun"] = "True"; + testProject.AdditionalProperties["PublishReadyToRunEmitSymbols"] = "True"; var testProjectInstance = _testAssetsManager.CreateTestProject(testProject) .Restore(Log, testProject.Name); @@ -125,6 +125,32 @@ public void It_creates_readytorun_symbols_when_switch_is_used(string targetFrame DoesImageHaveR2RInfo(classLibDll).ToString().Should().Be(true.ToString()); } + [Theory] + [InlineData("netcoreapp3.0")] + public void It_does_not_support_framework_dependent_publishing(string targetFramework) + { + var projectName = "FrameworkDependent"; + + var testProject = CreateTestProjectForR2RTesting( + EnvironmentInfo.GetCompatibleRid(targetFramework), + projectName, + "ClassLib"); + + testProject.AdditionalProperties["PublishReadyToRun"] = "True"; + + var testProjectInstance = _testAssetsManager.CreateTestProject(testProject) + .Restore(Log, testProject.Name); + + // TODO: This test should be changed to expect publishing to succeed when fixing #3109 and #3110. + // When fixing the issues, change the function name to reflect what we're testing, and change the test's expected + // behavior (check that the output assemblies exist and are R2R images). + var publishCommand = new PublishCommand(Log, Path.Combine(testProjectInstance.Path, testProject.Name)); + publishCommand.Execute("/p:SelfContained=false", "/v:n") + .Should() + .Fail() + .And.HaveStdOutContainingIgnoreCase("NETSDK1095"); + } + [Theory] [InlineData("netcoreapp3.0")] public void It_does_not_support_cross_platform_readytorun_compilation(string targetFramework) @@ -168,7 +194,7 @@ public void It_does_not_support_cross_platform_readytorun_compilation(string tar return; } - testProject.AdditionalProperties["ReadyToRun"] = "True"; + testProject.AdditionalProperties["PublishReadyToRun"] = "True"; var testProjectInstance = _testAssetsManager.CreateTestProject(testProject) .Restore(Log, testProject.Name); diff --git a/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToRunILLink.cs b/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToRunILLink.cs new file mode 100644 index 000000000000..add279e0a81e --- /dev/null +++ b/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToRunILLink.cs @@ -0,0 +1,331 @@ +using System; +using System.IO; +using System.Linq; +using System.Reflection.Metadata; +using System.Reflection.PortableExecutable; +using FluentAssertions; +using Microsoft.Extensions.DependencyModel; +using Microsoft.NET.TestFramework; +using Microsoft.NET.TestFramework.Assertions; +using Microsoft.NET.TestFramework.Commands; +using Microsoft.NET.TestFramework.ProjectConstruction; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.NET.Publish.Tests +{ + public class GivenThatWeWantToRunILLink : SdkTest + { + public GivenThatWeWantToRunILLink(ITestOutputHelper log) : base(log) + { + } + + [Theory] + [InlineData("netcoreapp3.0")] + public void ILLink_only_runs_when_switch_is_enabled(string targetFramework) + { + var projectName = "HelloWorld"; + var referenceProjectName = "ClassLibForILLink"; + var rid = EnvironmentInfo.GetCompatibleRid(targetFramework); + + var testProject = CreateTestProjectForILLinkTesting(targetFramework, projectName, referenceProjectName); + var testAsset = _testAssetsManager.CreateTestProject(testProject) + .Restore(Log, testProject.Name, args: $"/p:RuntimeIdentifier={rid}"); + + var publishCommand = new PublishCommand(Log, Path.Combine(testAsset.TestRoot, testProject.Name)); + publishCommand.Execute($"/p:RuntimeIdentifier={rid}", $"/p:SelfContained=true").Should().Pass(); + + var publishDirectory = publishCommand.GetOutputDirectory(targetFramework: targetFramework, runtimeIdentifier: rid).FullName; + var intermediateDirectory = publishCommand.GetIntermediateDirectory(targetFramework: targetFramework, runtimeIdentifier: rid).FullName; + var linkedDirectory = Path.Combine(intermediateDirectory, "linked"); + + Directory.Exists(linkedDirectory).Should().BeFalse(); + + var publishedDll = Path.Combine(publishDirectory, $"{projectName}.dll"); + var unusedDll = Path.Combine(publishDirectory, $"{referenceProjectName}.dll"); + var unusedFrameworkDll = Path.Combine(publishDirectory, $"{unusedFrameworkAssembly}.dll"); + + // Linker inputs are kept, including unused assemblies + File.Exists(publishedDll).Should().BeTrue(); + File.Exists(unusedDll).Should().BeTrue(); + File.Exists(unusedFrameworkDll).Should().BeTrue(); + + var depsFile = Path.Combine(publishDirectory, $"{projectName}.deps.json"); + DoesDepsFileHaveAssembly(depsFile, referenceProjectName).Should().BeTrue(); + DoesDepsFileHaveAssembly(depsFile, unusedFrameworkAssembly).Should().BeTrue(); + } + + [Theory] + [InlineData("netcoreapp3.0")] + public void ILLink_runs_and_creates_linked_app(string targetFramework) + { + var projectName = "HelloWorld"; + var referenceProjectName = "ClassLibForILLink"; + var rid = EnvironmentInfo.GetCompatibleRid(targetFramework); + + var testProject = CreateTestProjectForILLinkTesting(targetFramework, projectName, referenceProjectName); + var testAsset = _testAssetsManager.CreateTestProject(testProject) + .Restore(Log, testProject.Name, args: $"/p:RuntimeIdentifier={rid}"); + + var publishCommand = new PublishCommand(Log, Path.Combine(testAsset.TestRoot, testProject.Name)); + publishCommand.Execute($"/p:RuntimeIdentifier={rid}", $"/p:SelfContained=true", "/p:PublishTrimmed=true").Should().Pass(); + + var publishDirectory = publishCommand.GetOutputDirectory(targetFramework: targetFramework, runtimeIdentifier: rid).FullName; + var intermediateDirectory = publishCommand.GetIntermediateDirectory(targetFramework: targetFramework, runtimeIdentifier: rid).FullName; + var linkedDirectory = Path.Combine(intermediateDirectory, "linked"); + + Directory.Exists(linkedDirectory).Should().BeTrue(); + + var linkedDll = Path.Combine(linkedDirectory, $"{projectName}.dll"); + var publishedDll = Path.Combine(publishDirectory, $"{projectName}.dll"); + var unusedDll = Path.Combine(publishDirectory, $"{referenceProjectName}.dll"); + var unusedFrameworkDll = Path.Combine(publishDirectory, $"{unusedFrameworkAssembly}.dll"); + + // Intermediate assembly is kept by linker and published, but not unused assemblies + File.Exists(linkedDll).Should().BeTrue(); + File.Exists(publishedDll).Should().BeTrue(); + File.Exists(unusedDll).Should().BeFalse(); + File.Exists(unusedFrameworkDll).Should().BeFalse(); + + var depsFile = Path.Combine(publishDirectory, $"{projectName}.deps.json"); + DoesDepsFileHaveAssembly(depsFile, projectName).Should().BeTrue(); + DoesDepsFileHaveAssembly(depsFile, referenceProjectName).Should().BeFalse(); + DoesDepsFileHaveAssembly(depsFile, unusedFrameworkAssembly).Should().BeFalse(); + } + + [Theory] + [InlineData("netcoreapp3.0")] + public void ILLink_accepts_root_descriptor(string targetFramework) + { + var projectName = "HelloWorld"; + var referenceProjectName = "ClassLibForILLink"; + var rid = EnvironmentInfo.GetCompatibleRid(targetFramework); + + var testProject = CreateTestProjectForILLinkTesting(targetFramework, projectName, referenceProjectName); + var testAsset = _testAssetsManager.CreateTestProject(testProject) + .Restore(Log, testProject.Name, args: $"/p:RuntimeIdentifier={rid}"); + + var publishCommand = new PublishCommand(Log, Path.Combine(testAsset.TestRoot, testProject.Name)); + publishCommand.Execute($"/p:RuntimeIdentifier={rid}", $"/p:SelfContained=true", "/p:PublishTrimmed=true", + $"/p:TrimmerRootDescriptors={referenceProjectName}.xml").Should().Pass(); + + var publishDirectory = publishCommand.GetOutputDirectory(targetFramework: targetFramework, runtimeIdentifier: rid).FullName; + var publishedDll = Path.Combine(publishDirectory, $"{projectName}.dll"); + var unusedDll = Path.Combine(publishDirectory, $"{referenceProjectName}.dll"); + + // With root descriptor, linker keeps specified roots but removes unused methods + File.Exists(publishedDll).Should().BeTrue(); + File.Exists(unusedDll).Should().BeTrue(); + DoesImageHaveMethod(unusedDll, "UnusedMethod").Should().BeFalse(); + DoesImageHaveMethod(unusedDll, "UnusedMethodToRoot").Should().BeTrue(); + } + + [Theory] + [InlineData("netcoreapp3.0")] + public void ILLink_runs_incrementally(string targetFramework) + { + var projectName = "HelloWorld"; + var referenceProjectName = "ClassLibForILLink"; + var rid = EnvironmentInfo.GetCompatibleRid(targetFramework); + + var testProject = CreateTestProjectForILLinkTesting(targetFramework, projectName, referenceProjectName); + var testAsset = _testAssetsManager.CreateTestProject(testProject) + .Restore(Log, testProject.Name, args: $"/p:RuntimeIdentifier={rid}"); + + var publishCommand = new PublishCommand(Log, Path.Combine(testAsset.TestRoot, testProject.Name)); + + var publishDirectory = publishCommand.GetOutputDirectory(targetFramework: targetFramework, runtimeIdentifier: rid).FullName; + var intermediateDirectory = publishCommand.GetIntermediateDirectory(targetFramework: targetFramework, runtimeIdentifier: rid).FullName; + var linkedDirectory = Path.Combine(intermediateDirectory, "linked"); + + var linkSemaphore = Path.Combine(intermediateDirectory, "Link.semaphore"); + + publishCommand.Execute($"/p:RuntimeIdentifier={rid}", $"/p:SelfContained=true", "/p:PublishTrimmed=true").Should().Pass(); + DateTime semaphoreFirstModifiedTime = File.GetLastWriteTimeUtc(linkSemaphore); + + WaitForUtcNowToAdvance(); + + publishCommand.Execute($"/p:RuntimeIdentifier={rid}", $"/p:SelfContained=true", "/p:PublishTrimmed=true").Should().Pass(); + DateTime semaphoreSecondModifiedTime = File.GetLastWriteTimeUtc(linkSemaphore); + + semaphoreFirstModifiedTime.Should().Be(semaphoreSecondModifiedTime); + } + + [Theory] + [InlineData("netcoreapp3.0")] + public void ILLink_does_not_include_leftover_artifacts_on_second_run(string targetFramework) + { + var projectName = "HelloWorld"; + var referenceProjectName = "ClassLibForILLink"; + var rid = EnvironmentInfo.GetCompatibleRid(targetFramework); + + var testProject = CreateTestProjectForILLinkTesting(targetFramework, projectName, referenceProjectName); + var testAsset = _testAssetsManager.CreateTestProject(testProject) + .Restore(Log, testProject.Name, args: $"/p:RuntimeIdentifier={rid}"); + + var publishCommand = new PublishCommand(Log, Path.Combine(testAsset.TestRoot, testProject.Name)); + + var publishDirectory = publishCommand.GetOutputDirectory(targetFramework: targetFramework, runtimeIdentifier: rid).FullName; + var intermediateDirectory = publishCommand.GetIntermediateDirectory(targetFramework: targetFramework, runtimeIdentifier: rid).FullName; + var linkedDirectory = Path.Combine(intermediateDirectory, "linked"); + + var linkSemaphore = Path.Combine(intermediateDirectory, "Link.semaphore"); + + // Link, keeping classlib + publishCommand.Execute($"/p:RuntimeIdentifier={rid}", $"/p:SelfContained=true", "/p:PublishTrimmed=true", + $"/p:TrimmerRootDescriptors={referenceProjectName}.xml").Should().Pass(); + var publishedDllKeptFirstTimeOnly = Path.Combine(publishDirectory, $"{referenceProjectName}.dll"); + var linkedDllKeptFirstTimeOnly = Path.Combine(linkedDirectory, $"{referenceProjectName}.dll"); + File.Exists(linkedDllKeptFirstTimeOnly).Should().BeTrue(); + File.Exists(publishedDllKeptFirstTimeOnly).Should().BeTrue(); + + // Delete kept dll from publish output (works around lack of incremental publish) + File.Delete(publishedDllKeptFirstTimeOnly); + + // Modify input timestamp to force a re-build and re-link + WaitForUtcNowToAdvance(); + File.SetLastWriteTimeUtc(Path.Combine(testAsset.TestRoot, testProject.Name, $"{projectName}.cs"), DateTime.UtcNow); + + // Link, discarding classlib + publishCommand.Execute($"/p:RuntimeIdentifier={rid}", $"/p:SelfContained=true", "/p:PublishTrimmed=true").Should().Pass(); + File.Exists(linkedDllKeptFirstTimeOnly).Should().BeFalse(); + File.Exists(publishedDllKeptFirstTimeOnly).Should().BeFalse(); + + // "linked" intermediate directory does not pollute the publish output + Directory.Exists(Path.Combine(publishDirectory, "linked")).Should().BeFalse(); + } + + [Theory] + [InlineData("netcoreapp3.0")] + public void ILLink_runs_on_portable_app(string targetFramework) + { + var projectName = "HelloWorld"; + var referenceProjectName = "ClassLibForILLink"; + + var testProject = CreateTestProjectForILLinkTesting(targetFramework, projectName, referenceProjectName); + var testAsset = _testAssetsManager.CreateTestProject(testProject) + .Restore(Log, testProject.Name); + + var publishCommand = new PublishCommand(Log, Path.Combine(testAsset.TestRoot, testProject.Name)); + publishCommand.Execute("/p:PublishTrimmed=true").Should().Pass(); + + var publishDirectory = publishCommand.GetOutputDirectory(targetFramework: targetFramework).FullName; + var intermediateDirectory = publishCommand.GetIntermediateDirectory(targetFramework: targetFramework).FullName; + var linkedDirectory = Path.Combine(intermediateDirectory, "linked"); + + Directory.Exists(linkedDirectory).Should().BeTrue(); + + var linkedDll = Path.Combine(linkedDirectory, $"{projectName}.dll"); + var publishedDll = Path.Combine(publishDirectory, $"{projectName}.dll"); + var unusedDll = Path.Combine(publishDirectory, $"{referenceProjectName}.dll"); + + File.Exists(linkedDll).Should().BeTrue(); + File.Exists(publishedDll).Should().BeTrue(); + File.Exists(unusedDll).Should().BeFalse(); + + var depsFile = Path.Combine(publishDirectory, $"{projectName}.deps.json"); + DoesDepsFileHaveAssembly(depsFile, projectName).Should().BeTrue(); + DoesDepsFileHaveAssembly(depsFile, referenceProjectName).Should().BeFalse(); + } + + private static bool DoesImageHaveMethod(string path, string methodNameToCheck) + { + using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read)) + using (var peReader = new PEReader(fs)) + { + var metadataReader = peReader.GetMetadataReader(); + foreach (var handle in metadataReader.MethodDefinitions) + { + var methodDefinition = metadataReader.GetMethodDefinition(handle); + string methodName = metadataReader.GetString(methodDefinition.Name); + if (methodName == methodNameToCheck) + return true; + } + } + return false; + } + + private static bool DoesDepsFileHaveAssembly(string depsFilePath, string assemblyName) + { + DependencyContext dependencyContext; + using (var fs = File.OpenRead(depsFilePath)) + { + dependencyContext = new DependencyContextJsonReader().Read(fs); + } + + return dependencyContext.RuntimeLibraries.Any(l => + l.RuntimeAssemblyGroups.Any(rag => + rag.AssetPaths.Any(f => + Path.GetFileName(f) == $"{assemblyName}.dll"))); + } + + static string unusedFrameworkAssembly = "System.IO"; + + private TestPackageReference GetPackageReference(TestProject project) + { + var asset = _testAssetsManager.CreateTestProject(project, project.Name).Restore(Log, project.Name); + var pack = new PackCommand(Log, Path.Combine(asset.TestRoot, project.Name)); + pack.Execute().Should().Pass(); + + return new TestPackageReference(project.Name, "1.0.0", pack.GetNuGetPackage(project.Name)); + } + + private TestProject CreateTestProjectForILLinkTesting(string targetFramework, string mainProjectName, string referenceProjectName) + { + var referenceProject = new TestProject() + { + Name = referenceProjectName, + TargetFrameworks = targetFramework, + IsSdkProject = true + }; + referenceProject.SourceFiles[$"{referenceProjectName}.cs"] = @" +using System; +public class ClassLib +{ + public void UnusedMethod() + { + } + + public void UnusedMethodToRoot() + { + } +} +"; + + var packageReference = GetPackageReference(referenceProject); + + var testProject = new TestProject() + { + Name = mainProjectName, + TargetFrameworks = targetFramework, + IsSdkProject = true, + PackageReferences = { packageReference } + }; + + testProject.AdditionalProperties.Add("RestoreAdditionalProjectSources", Path.GetDirectoryName(packageReference.NupkgPath)); + + testProject.SourceFiles[$"{mainProjectName}.cs"] = @" +using System; +public class Program +{ + public static void Main() + { + Console.WriteLine(""Hello world""); + } +} +"; + + testProject.SourceFiles[$"{referenceProjectName}.xml"] = $@" + + + + + + + +"; + + return testProject; + } + } +} diff --git a/src/Tests/Microsoft.NET.Publish.Tests/PublishItemsOutputGroupTests.cs b/src/Tests/Microsoft.NET.Publish.Tests/PublishItemsOutputGroupTests.cs new file mode 100644 index 000000000000..e101cbc29eda --- /dev/null +++ b/src/Tests/Microsoft.NET.Publish.Tests/PublishItemsOutputGroupTests.cs @@ -0,0 +1,106 @@ +using System.Collections.Generic; +using System.IO; +using FluentAssertions; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.NET.TestFramework; +using Microsoft.NET.TestFramework.Assertions; +using Microsoft.NET.TestFramework.Commands; +using Microsoft.NET.TestFramework.ProjectConstruction; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.NET.Publish.Tests +{ + public class PublishItemsOutputGroupTests : SdkTest + { + public PublishItemsOutputGroupTests(ITestOutputHelper log) : base(log) + { + } + + private readonly static List FrameworkAssemblies = new List() + { + "api-ms-win-core-console-l1-1-0.dll", + "System.Runtime.dll", + "WindowsBase.dll", + }; + + [Fact] + public void GroupPopulatedWithRid() + { + var testProject = this.SetupProject(); + var testAsset = _testAssetsManager.CreateTestProject(testProject); + + var restoreCommand = new RestoreCommand(Log, testAsset.Path, testProject.Name); + restoreCommand + .Execute() + .Should() + .Pass(); + + var buildCommand = new BuildCommand(Log, testAsset.Path, testProject.Name); + buildCommand + .Execute("/p:RuntimeIdentifier=win-x86", "/t:PublishItemsOutputGroup") + .Should() + .Pass(); + + var testOutputDir = new DirectoryInfo(Path.Combine(testAsset.Path, testProject.Name, "TestOutput")); + Log.WriteLine("Contents of PublishItemsOutputGroup dumped to '{0}'.", testOutputDir.FullName); + + // Check for the existence of a few specific files that should be in the directory where the + // contents of PublishItemsOutputGroup were dumped to make sure it's getting populated. + testOutputDir.Should().HaveFile($"{testProject.Name}.exe"); + testOutputDir.Should().HaveFiles(FrameworkAssemblies); + } + + [Fact] + public void GroupNotPopulatedWithoutRid() + { + var testProject = this.SetupProject(); + var testAsset = _testAssetsManager.CreateTestProject(testProject); + + var restoreCommand = new RestoreCommand(Log, testAsset.Path, testProject.Name); + restoreCommand + .Execute() + .Should() + .Pass(); + + var buildCommand = new BuildCommand(Log, testAsset.Path, testProject.Name); + buildCommand + .Execute("/t:PublishItemsOutputGroup") + .Should() + .Pass(); + + var testOutputDir = new DirectoryInfo(Path.Combine(testAsset.Path, testProject.Name, "TestOutput")); + Log.WriteLine("Contents of PublishItemsOutputGroup dumped to '{0}'.", testOutputDir.FullName); + + // Since no RID was specified the output group should only contain framework dependent output + testOutputDir.Should().HaveFile($"{testProject.Name}{Constants.ExeSuffix}"); + testOutputDir.Should().NotHaveFiles(FrameworkAssemblies); + } + + private TestProject SetupProject() + { + var testProject = new TestProject() + { + Name = "TestPublishOutputGroup", + TargetFrameworks = "netcoreapp3.0", + IsSdkProject = true, + IsExe = true + }; + + testProject.AdditionalProperties["RuntimeIdentifiers"] = "win-x86"; + + // Use a test-specific packages folder + testProject.AdditionalProperties["RestorePackagesPath"] = @"$(MSBuildProjectDirectory)\..\pkg"; + + // Add a target that will dump the contents of the PublishItemsOutputGroup to + // a test directory after building. + testProject.CopyFilesTargets.Add(new CopyFilesTarget( + "CopyPublishItemsOutputGroup", + "PublishItemsOutputGroup", + "@(PublishItemsOutputGroupOutputs)", + "$(MSBuildProjectDirectory)\\TestOutput")); + + return testProject; + } + } +} diff --git a/src/Tests/Microsoft.NET.TestFramework/CopyFilesTarget.cs b/src/Tests/Microsoft.NET.TestFramework/CopyFilesTarget.cs new file mode 100644 index 000000000000..5b0bd2556e93 --- /dev/null +++ b/src/Tests/Microsoft.NET.TestFramework/CopyFilesTarget.cs @@ -0,0 +1,25 @@ +// 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.NET.TestFramework +{ + /// + /// Represents a target that will copy some set of files to a given location after some other target completes. + /// Useful for verifying the contents of an output group in a test. + /// + public class CopyFilesTarget + { + public CopyFilesTarget(string targetName, string targetToRunAfter, string sourceFiles, string destination) + { + TargetName = targetName; + TargetToRunAfter = targetToRunAfter; + SourceFiles = sourceFiles; + Destination = destination; + } + + public string TargetName { get; private set; } + public string TargetToRunAfter { get; private set; } + public string SourceFiles { get; private set; } + public string Destination { get; private set; } + } +} diff --git a/src/Tests/Microsoft.NET.TestFramework/ProjectConstruction/TestProject.cs b/src/Tests/Microsoft.NET.TestFramework/ProjectConstruction/TestProject.cs index d5342264ecc3..68ee01b4d360 100644 --- a/src/Tests/Microsoft.NET.TestFramework/ProjectConstruction/TestProject.cs +++ b/src/Tests/Microsoft.NET.TestFramework/ProjectConstruction/TestProject.cs @@ -36,6 +36,8 @@ public class TestProject public List PackageReferences { get; } = new List(); public List DotNetCliToolReferences { get; } = new List(); + + public List CopyFilesTargets { get; } = new List(); public Dictionary SourceFiles { get; } = new Dictionary(); @@ -274,6 +276,22 @@ internal void Create(TestAsset targetTestAsset, string testProjectsSourceFolder) new XAttribute("Include", reference))); } } + + if (this.CopyFilesTargets.Any()) + { + foreach (var copyFilesTarget in CopyFilesTargets) + { + var target = new XElement(ns + "Target", + new XAttribute("Name", copyFilesTarget.TargetName), + new XAttribute("AfterTargets", copyFilesTarget.TargetToRunAfter)); + + target.Add(new XElement(ns + "Copy", + new XAttribute("SourceFiles", copyFilesTarget.SourceFiles), + new XAttribute("DestinationFolder", copyFilesTarget.Destination))); + + projectXml.Root.Add(target); + } + } using (var file = File.CreateText(targetProjectPath)) {