From 3f5935dd2d9ecb7716244e0c20c3bfca92938515 Mon Sep 17 00:00:00 2001 From: Joseph Tremoulet Date: Fri, 26 Jan 2018 15:31:09 -0500 Subject: [PATCH 1/8] Pass ref assemblies to link in portable publish Include anything in ReferencePath that is not part of the published set to make sure the linker can resolve references in the published set. Include them as "platform" libraries since the link action for these should always be 'Skip' when doing a portable publish. --- .../ILLink.Tasks/ILLink.Tasks.targets | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/corebuild/integration/ILLink.Tasks/ILLink.Tasks.targets b/corebuild/integration/ILLink.Tasks/ILLink.Tasks.targets index ce76e7136831..1a2344ea14de 100644 --- a/corebuild/integration/ILLink.Tasks/ILLink.Tasks.targets +++ b/corebuild/integration/ILLink.Tasks/ILLink.Tasks.targets @@ -281,6 +281,11 @@ <_ManagedAssembliesToLink Include="@(IntermediateAssembly)" /> <_ManagedAssembliesToLink Include="@(_ManagedResolvedAssembliesToPublish)" /> + + + <_ReferencedLibraries Include="@(ReferencePath->'%(ResolvedPath)')" Exclude="@(_ManagedAssembliesToLink)" /> + <_ManagedAssembliesToLink Include="@(_ReferencedLibraries)" /> + @@ -363,7 +368,7 @@ - @@ -373,13 +378,20 @@ - - + + + + + + From d3cbd4c320935e6d4e67fa81ae19e926ae1b2fb1 Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Thu, 15 Feb 2018 15:34:22 -0800 Subject: [PATCH 2/8] Add portable publish tests Factor the integration tests so that project setup is done once per project, allowing multiple testcases to invoke the linker on the same project without excess overhead. Also add testcases exercising portable publish for helloworld and musicstore. --- corebuild/integration/test/CommandRunner.cs | 3 +- corebuild/integration/test/HelloWorldTest.cs | 34 +++- .../integration/test/IntegrationTestBase.cs | 57 ++++-- corebuild/integration/test/MusicStoreTest.cs | 178 +++++++++++------- corebuild/integration/test/WebApiTest.cs | 23 ++- 5 files changed, 194 insertions(+), 101 deletions(-) diff --git a/corebuild/integration/test/CommandRunner.cs b/corebuild/integration/test/CommandRunner.cs index 58c4b3416743..21ac2a47baf4 100644 --- a/corebuild/integration/test/CommandRunner.cs +++ b/corebuild/integration/test/CommandRunner.cs @@ -67,6 +67,7 @@ public int Run(out string commandOutput) RedirectStandardOutput = true, RedirectStandardError = true, }; + outputHelper.WriteLine($"from caller working directory {Environment.CurrentDirectory}"); if (!String.IsNullOrEmpty(args)) { psi.Arguments = args; outputHelper.WriteLine($"{command} {args}"); @@ -74,7 +75,7 @@ public int Run(out string commandOutput) outputHelper.WriteLine($"{command}"); } if (!String.IsNullOrEmpty(workingDir)) { - outputHelper.WriteLine("$working directory: {workingDir}"); + outputHelper.WriteLine($"working directory: {workingDir}"); psi.WorkingDirectory = workingDir; } if (!String.IsNullOrEmpty(additionalPath)) { diff --git a/corebuild/integration/test/HelloWorldTest.cs b/corebuild/integration/test/HelloWorldTest.cs index 009601e8875c..23e4662c2062 100644 --- a/corebuild/integration/test/HelloWorldTest.cs +++ b/corebuild/integration/test/HelloWorldTest.cs @@ -7,11 +7,21 @@ namespace ILLink.Tests { public class HelloWorldTest : IntegrationTestBase { - public HelloWorldTest(ITestOutputHelper output) : base(output) {} + private string csproj; + + public HelloWorldTest(ITestOutputHelper output) : base(output) { + csproj = SetupProject(); + } public string SetupProject() { string projectRoot = "helloworld"; + string csproj = Path.Combine(projectRoot, $"{projectRoot}.csproj"); + + if (File.Exists(csproj)) { + output.WriteLine($"using existing project {csproj}"); + return csproj; + } if (Directory.Exists(projectRoot)) { Directory.Delete(projectRoot, true); @@ -24,20 +34,28 @@ public string SetupProject() Assert.True(false); } - string csproj = Path.Combine(projectRoot, $"{projectRoot}.csproj"); + AddLinkerReference(csproj); + return csproj; } [Fact] - public void RunHelloWorld() + public void RunHelloWorldStandalone() { - string csproj = SetupProject(); - - AddLinkerReference(csproj); + string executablePath = BuildAndLink(csproj, selfContained: true); + CheckOutput(executablePath, selfContained: true); + } - BuildAndLink(csproj, null); + [Fact] + public void RunHelloWorldPortable() + { + string target = BuildAndLink(csproj, selfContained: false); + CheckOutput(target, selfContained: false); + } - int ret = RunApp(csproj, out string commandOutput); + void CheckOutput(string target, bool selfContained = false) + { + int ret = RunApp(target, out string commandOutput, selfContained: selfContained); Assert.True(ret == 0); Assert.True(commandOutput.Contains("Hello World!")); } diff --git a/corebuild/integration/test/IntegrationTestBase.cs b/corebuild/integration/test/IntegrationTestBase.cs index 951e5d575aeb..4c2526065bdd 100644 --- a/corebuild/integration/test/IntegrationTestBase.cs +++ b/corebuild/integration/test/IntegrationTestBase.cs @@ -60,14 +60,18 @@ protected int RunCommand(string command, string args, string workingDir, string /// that the project already contains a reference to the /// linker task package. /// Optionally takes a list of root descriptor files. + /// Returns the path to the built app, either the renamed + /// host for self-contained publish, or the dll containing + /// the entry point. /// - public void BuildAndLink(string csproj, List rootFiles = null, Dictionary extraPublishArgs = null) + public string BuildAndLink(string csproj, List rootFiles = null, Dictionary extraPublishArgs = null, bool selfContained = false) { - string rid = context.RuntimeIdentifier; - string config = context.Configuration; string demoRoot = Path.GetDirectoryName(csproj); string publishArgs = $"publish -r {rid} -c {config} /v:n /p:ShowLinkerSizeComparison=true"; + if (selfContained) { + publishArgs += $" -r {context.RuntimeIdentifier}"; + } string rootFilesStr; if (rootFiles != null && rootFiles.Any()) { rootFilesStr = String.Join(";", rootFiles); @@ -83,28 +87,45 @@ public void BuildAndLink(string csproj, List rootFiles = null, Dictionar if (ret != 0) { output.WriteLine("publish failed, returning " + ret); Assert.True(false); - return; } - } - public int RunApp(string csproj, out string processOutput, int timeout = Int32.MaxValue, string terminatingOutput = null) - { - string demoRoot = Path.GetDirectoryName(csproj); // detect the target framework for which the app was published string tfmDir = Path.Combine(demoRoot, "bin", context.Configuration); string tfm = Directory.GetDirectories(tfmDir).Select(p => Path.GetFileName(p)).Single(); - string executablePath = Path.Combine(tfmDir, tfm, - context.RuntimeIdentifier, "publish", - Path.GetFileNameWithoutExtension(csproj) - ); - if (context.RuntimeIdentifier.Contains("win")) { - executablePath += ".exe"; + string builtApp = Path.Combine(tfmDir, tfm); + if (selfContained) { + builtApp = Path.Combine(builtApp, context.RuntimeIdentifier); } - Assert.True(File.Exists(executablePath)); + builtApp = Path.Combine(builtApp, "publish", + Path.GetFileNameWithoutExtension(csproj)); + if (selfContained) { + if (context.RuntimeIdentifier.Contains("win")) { + builtApp += ".exe"; + } + } else { + builtApp += ".dll"; + } + Assert.True(File.Exists(builtApp)); + return builtApp; + } - int ret = RunCommand(executablePath, null, - Directory.GetParent(executablePath).FullName, - null, out processOutput, timeout, terminatingOutput); + public int RunApp(string target, out string processOutput, int timeout = Int32.MaxValue, + string terminatingOutput = null, bool selfContained = false) + { + Assert.True(File.Exists(target)); + int ret; + if (selfContained) { + ret = RunCommand( + target, null, + Directory.GetParent(target).FullName, + null, out processOutput, timeout, terminatingOutput); + } else { + ret = RunCommand( + Path.GetFullPath(context.DotnetToolPath), + Path.GetFullPath(target), + Directory.GetParent(target).FullName, + null, out processOutput, timeout, terminatingOutput); + } return ret; } diff --git a/corebuild/integration/test/MusicStoreTest.cs b/corebuild/integration/test/MusicStoreTest.cs index 7aa53d414aff..7ad72469a3d0 100644 --- a/corebuild/integration/test/MusicStoreTest.cs +++ b/corebuild/integration/test/MusicStoreTest.cs @@ -10,8 +10,6 @@ namespace ILLink.Tests { public class MusicStoreTest : IntegrationTestBase { - public MusicStoreTest(ITestOutputHelper output) : base(output) {} - private static List rootFiles = new List { "MusicStoreReflection.xml" }; private static string gitRepo = "http://github.com/aspnet/JitBench"; @@ -34,40 +32,138 @@ public MusicStoreTest(ITestOutputHelper output) : base(output) {} // The version of Microsoft.AspNetCore.All to publish with. private static string aspNetVersion = "2.1.0-preview1-27654"; + private static Dictionary extraPublishArgs; + private static Dictionary ExtraPublishArgs + { + get { + if (extraPublishArgs != null) { + return extraPublishArgs; + } + extraPublishArgs = new Dictionary(); + extraPublishArgs.Add("JITBENCH_FRAMEWORK_VERSION", runtimeVersion); + extraPublishArgs.Add("JITBENCH_ASPNET_VERSION", aspNetVersion); + return extraPublishArgs; + } + } + + private static string csproj; + + public MusicStoreTest(ITestOutputHelper output) : base(output) { + csproj = SetupProject(); + + // MusicStore targets .NET Core 2.1, so it must be built + // using an SDK that can target 2.1. We obtain that SDK + // here. + context.DotnetToolPath = ObtainSDK(context.TestBin, repoName); + } + + [Fact] + public void RunMusicStoreStandalone() + { + string executablePath = BuildAndLink(csproj, rootFiles, ExtraPublishArgs, selfContained: true); + CheckOutput(executablePath, selfContained: true); + } + [Fact] - public void RunMusicStore() + public void RunMusicStorePortable() { - string csproj = SetupProject(); + string target = BuildAndLink(csproj, rootFiles, ExtraPublishArgs, selfContained: false); + CheckOutput(target, selfContained: false); + } + + void CheckOutput(string target, bool selfContained = false) + { + int ret = RunApp(target, out string commandOutput, selfContained: selfContained); + + Assert.True(commandOutput.Contains("Starting request to http://localhost:5000")); + Assert.True(commandOutput.Contains("Response: OK")); + Assert.True(commandOutput.Contains("Running 100 requests")); + Assert.True(ret == 0); + } + + // returns path to .csproj project file + string SetupProject() + { + int ret; + string demoRoot = Path.Combine(repoName, Path.Combine("src", "MusicStore")); + string csproj = Path.Combine(demoRoot, "MusicStore.csproj"); + + if (File.Exists(csproj)) { + output.WriteLine($"using existing project {csproj}"); + return csproj; + } + + if (Directory.Exists(repoName)) { + Directory.Delete(repoName, true); + } + + ret = RunCommand("git", $"clone {gitRepo} {repoName}"); + if (ret != 0) { + output.WriteLine("git failed"); + Assert.True(false); + } + + if (!Directory.Exists(demoRoot)) { + output.WriteLine($"{demoRoot} does not exist"); + Assert.True(false); + } + + ret = RunCommand("git", $"checkout {gitRevision}", demoRoot); + if (ret != 0) { + output.WriteLine($"problem checking out revision {gitRevision}"); + Assert.True(false); + } // Copy root files into the project directory - string demoRoot= Path.GetDirectoryName(csproj); CopyRootFiles(demoRoot); // This is necessary because JitBench comes with a // NuGet.Config that has a line, preventing // NuGet.Config sources defined in outer directories from // applying. - string nugetConfig = Path.Combine("JitBench", "NuGet.config"); + string nugetConfig = Path.Combine(repoName, "NuGet.config"); AddLocalNugetFeedAfterClear(nugetConfig); AddLinkerReference(csproj); - Dictionary extraPublishArgs = new Dictionary(); - extraPublishArgs.Add("JITBENCH_FRAMEWORK_VERSION", runtimeVersion); - extraPublishArgs.Add("JITBENCH_ASPNET_VERSION", aspNetVersion); - BuildAndLink(csproj, rootFiles, extraPublishArgs); + AddGlobalJson(repoName); - int ret = RunApp(csproj, out string commandOutput); - Assert.True(commandOutput.Contains("Starting request to http://localhost:5000")); - Assert.True(commandOutput.Contains("Response: OK")); - Assert.True(commandOutput.Contains("Running 100 requests")); - Assert.True(ret == 0); + return csproj; + } + + void AddGlobalJson(string repoDir) + { + string globalJson = Path.Combine(repoDir, "global.json"); + string globalJsonContents = "{ \"sdk\": { \"version\": \"" + sdkVersion + "\" } }\n"; + File.WriteAllText(globalJson, globalJsonContents); + } + + + string GetDotnetToolPath(string dotnetDir) + { + string dotnetToolName = Directory.GetFiles(dotnetDir) + .Select(p => Path.GetFileName(p)) + .Where(p => p.Contains("dotnet")) + .Single(); + string dotnetToolPath = Path.Combine(dotnetDir, dotnetToolName); + + if (!File.Exists(dotnetToolPath)) { + output.WriteLine("repo-local dotnet tool does not exist."); + Assert.True(false); + } + + return dotnetToolPath; } string ObtainSDK(string rootDir, string repoDir) { int ret; string dotnetDirName = ".dotnet"; + string dotnetDir = Path.Combine(rootDir, dotnetDirName); + if (Directory.Exists(dotnetDir)) { + return GetDotnetToolPath(dotnetDir); + } + string dotnetInstall = Path.Combine(Path.GetFullPath(repoDir), "dotnet-install"); if (context.RuntimeIdentifier.Contains("win")) { dotnetInstall += ".ps1"; @@ -103,57 +199,7 @@ string ObtainSDK(string rootDir, string repoDir) } } - string dotnetDir = Path.Combine(rootDir, dotnetDirName); - string dotnetToolName = Directory.GetFiles(dotnetDir) - .Select(p => Path.GetFileName(p)) - .Where(p => p.Contains("dotnet")) - .Single(); - string dotnetToolPath = Path.Combine(dotnetDir, dotnetToolName); - if (!File.Exists(dotnetToolPath)) { - output.WriteLine("repo-local dotnet tool does not exist."); - Assert.True(false); - } - - string globalJson = Path.Combine(repoDir, "global.json"); - string globalJsonContents = "{ \"sdk\": { \"version\": \"" + sdkVersion + "\" } }\n"; - File.WriteAllText(globalJson, globalJsonContents); - - return dotnetToolPath; - } - - // returns path to .csproj project file - string SetupProject() - { - int ret; - if (Directory.Exists(repoName)) { - Directory.Delete(repoName, true); - } - - ret = RunCommand("git", $"clone {gitRepo}"); - if (ret != 0) { - output.WriteLine("git failed"); - Assert.True(false); - } - - string demoRoot = Path.Combine("JitBench", Path.Combine("src", "MusicStore")); - if (!Directory.Exists(demoRoot)) { - output.WriteLine($"{demoRoot} does not exist"); - Assert.True(false); - } - - ret = RunCommand("git", $"checkout {gitRevision}", demoRoot); - if (ret != 0) { - output.WriteLine($"problem checking out revision {gitRevision}"); - Assert.True(false); - } - - // MusicStore targets .NET Core 2.1, so it must be built - // using an SDK that can target 2.1. We obtain that SDK - // here. - context.DotnetToolPath = ObtainSDK(context.TestBin, repoName); - - string csproj = Path.Combine(demoRoot, "MusicStore.csproj"); - return csproj; + return GetDotnetToolPath(dotnetDir); } static void CopyRootFiles(string demoRoot) diff --git a/corebuild/integration/test/WebApiTest.cs b/corebuild/integration/test/WebApiTest.cs index 2d948e951aec..ed4420a48f62 100644 --- a/corebuild/integration/test/WebApiTest.cs +++ b/corebuild/integration/test/WebApiTest.cs @@ -8,11 +8,21 @@ namespace ILLink.Tests { public class WebApiTest : IntegrationTestBase { - public WebApiTest(ITestOutputHelper output) : base(output) {} + private string csproj; + + public WebApiTest(ITestOutputHelper output) : base(output) { + csproj = SetupProject(); + } public string SetupProject() { string projectRoot = "webapi"; + string csproj = Path.Combine(projectRoot, $"{projectRoot}.csproj"); + + if (File.Exists(csproj)) { + output.WriteLine($"using existing project {csproj}"); + return csproj; + } if (Directory.Exists(projectRoot)) { Directory.Delete(projectRoot, true); @@ -25,7 +35,10 @@ public string SetupProject() Assert.True(false); } - string csproj = Path.Combine(projectRoot, $"{projectRoot}.csproj"); + PreventPublishFiltering(csproj); + + AddLinkerReference(csproj); + return csproj; } @@ -51,12 +64,6 @@ private void PreventPublishFiltering(string csproj) { [Fact] public void RunWebApi() { - string csproj = SetupProject(); - - PreventPublishFiltering(csproj); - - AddLinkerReference(csproj); - BuildAndLink(csproj); string terminatingOutput = "Now listening on: http://localhost:5000"; From e08ccdfb39a90d8cd855c369e29a0605bf6b4016 Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Tue, 20 Feb 2018 12:30:12 -0800 Subject: [PATCH 3/8] Remove RID argument for portable publish --- corebuild/integration/test/IntegrationTestBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/corebuild/integration/test/IntegrationTestBase.cs b/corebuild/integration/test/IntegrationTestBase.cs index 4c2526065bdd..99218ba3e36a 100644 --- a/corebuild/integration/test/IntegrationTestBase.cs +++ b/corebuild/integration/test/IntegrationTestBase.cs @@ -68,7 +68,7 @@ public string BuildAndLink(string csproj, List rootFiles = null, Diction { string demoRoot = Path.GetDirectoryName(csproj); - string publishArgs = $"publish -r {rid} -c {config} /v:n /p:ShowLinkerSizeComparison=true"; + string publishArgs = $"publish -c {context.Configuration} /v:n /p:ShowLinkerSizeComparison=true"; if (selfContained) { publishArgs += $" -r {context.RuntimeIdentifier}"; } From 65750f26fc882b762829faec87710433c4531ec4 Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Tue, 20 Feb 2018 12:31:49 -0800 Subject: [PATCH 4/8] Don't use asp.net manifest for musicstore portable test --- .../ILLink.Tasks/ILLink.Tasks.targets | 4 ++-- corebuild/integration/test/MusicStoreTest.cs | 22 ++++++++++--------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/corebuild/integration/ILLink.Tasks/ILLink.Tasks.targets b/corebuild/integration/ILLink.Tasks/ILLink.Tasks.targets index 1a2344ea14de..6a4733d7c4e8 100644 --- a/corebuild/integration/ILLink.Tasks/ILLink.Tasks.targets +++ b/corebuild/integration/ILLink.Tasks/ILLink.Tasks.targets @@ -282,7 +282,8 @@ <_ManagedAssembliesToLink Include="@(_ManagedResolvedAssembliesToPublish)" /> - + <_ReferencedLibraries Include="@(ReferencePath->'%(ResolvedPath)')" Exclude="@(_ManagedAssembliesToLink)" /> <_ManagedAssembliesToLink Include="@(_ReferencedLibraries)" /> @@ -391,7 +392,6 @@ - diff --git a/corebuild/integration/test/MusicStoreTest.cs b/corebuild/integration/test/MusicStoreTest.cs index 7ad72469a3d0..a28e996d2489 100644 --- a/corebuild/integration/test/MusicStoreTest.cs +++ b/corebuild/integration/test/MusicStoreTest.cs @@ -32,17 +32,17 @@ public class MusicStoreTest : IntegrationTestBase // The version of Microsoft.AspNetCore.All to publish with. private static string aspNetVersion = "2.1.0-preview1-27654"; - private static Dictionary extraPublishArgs; - private static Dictionary ExtraPublishArgs + private static Dictionary versionPublishArgs; + private static Dictionary VersionPublishArgs { get { - if (extraPublishArgs != null) { - return extraPublishArgs; + if (versionPublishArgs != null) { + return versionPublishArgs; } - extraPublishArgs = new Dictionary(); - extraPublishArgs.Add("JITBENCH_FRAMEWORK_VERSION", runtimeVersion); - extraPublishArgs.Add("JITBENCH_ASPNET_VERSION", aspNetVersion); - return extraPublishArgs; + versionPublishArgs = new Dictionary(); + versionPublishArgs.Add("JITBENCH_FRAMEWORK_VERSION", runtimeVersion); + versionPublishArgs.Add("JITBENCH_ASPNET_VERSION", aspNetVersion); + return versionPublishArgs; } } @@ -60,14 +60,16 @@ public MusicStoreTest(ITestOutputHelper output) : base(output) { [Fact] public void RunMusicStoreStandalone() { - string executablePath = BuildAndLink(csproj, rootFiles, ExtraPublishArgs, selfContained: true); + string executablePath = BuildAndLink(csproj, rootFiles, VersionPublishArgs, selfContained: true); CheckOutput(executablePath, selfContained: true); } [Fact] public void RunMusicStorePortable() { - string target = BuildAndLink(csproj, rootFiles, ExtraPublishArgs, selfContained: false); + Dictionary extraPublishArgs = new Dictionary(VersionPublishArgs); + extraPublishArgs.Add("PublishWithAspNetCoreTargetManifest", "false"); + string target = BuildAndLink(csproj, null, extraPublishArgs, selfContained: false); CheckOutput(target, selfContained: false); } From 814a30e27ddbc95ea6f264ffda5bdbf2ed23c5e1 Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Tue, 20 Feb 2018 13:27:54 -0800 Subject: [PATCH 5/8] Fix WebApi test --- corebuild/integration/test/WebApiTest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/corebuild/integration/test/WebApiTest.cs b/corebuild/integration/test/WebApiTest.cs index ed4420a48f62..454871389b55 100644 --- a/corebuild/integration/test/WebApiTest.cs +++ b/corebuild/integration/test/WebApiTest.cs @@ -64,10 +64,10 @@ private void PreventPublishFiltering(string csproj) { [Fact] public void RunWebApi() { - BuildAndLink(csproj); + string target = BuildAndLink(csproj); string terminatingOutput = "Now listening on: http://localhost:5000"; - int ret = RunApp(csproj, out string commandOutput, 60000, terminatingOutput); + int ret = RunApp(target, out string commandOutput, 60000, terminatingOutput); Assert.True(commandOutput.Contains("Application started. Press Ctrl+C to shut down.")); Assert.True(commandOutput.Contains(terminatingOutput)); } From 2b73730bf66585d51760c1173d60baf242425eb5 Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Tue, 20 Feb 2018 14:32:35 -0800 Subject: [PATCH 6/8] Set up webapi portable publish test --- corebuild/integration/test/WebApiTest.cs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/corebuild/integration/test/WebApiTest.cs b/corebuild/integration/test/WebApiTest.cs index 454871389b55..c7e8683e0210 100644 --- a/corebuild/integration/test/WebApiTest.cs +++ b/corebuild/integration/test/WebApiTest.cs @@ -62,12 +62,23 @@ private void PreventPublishFiltering(string csproj) { } [Fact] - public void RunWebApi() + public void RunWebApiStandalone() { - string target = BuildAndLink(csproj); + string executablePath = BuildAndLink(csproj, selfContained: true); + CheckOutput(executablePath, selfContained: true); + } + + [Fact] + public void RunWebApiPortable() + { + string target = BuildAndLink(csproj, selfContained: false); + CheckOutput(target, selfContained: false); + } + void CheckOutput(string target, bool selfContained = false) + { string terminatingOutput = "Now listening on: http://localhost:5000"; - int ret = RunApp(target, out string commandOutput, 60000, terminatingOutput); + int ret = RunApp(target, out string commandOutput, 60000, terminatingOutput, selfContained: selfContained); Assert.True(commandOutput.Contains("Application started. Press Ctrl+C to shut down.")); Assert.True(commandOutput.Contains(terminatingOutput)); } From 97cc6723951272f1e02d13159b4f2107825a69c2 Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Mon, 26 Feb 2018 09:52:08 -0800 Subject: [PATCH 7/8] Prevent inclusion of duplicate assemblies in reference set We want to avoid including in _ReferencedLibraries any ref assemblies from ReferencePath that also exist with the same filename as publish assemblies. Otherwise, the ref assemblies become part of the linker "platform" assemblies, and they get skipped during portable publish. This would be incorrect if ReferencePath includes any ref assemblies for non-shared libraries. --- .../ILLink.Tasks/ILLink.Tasks.targets | 42 +++++++++++++------ 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/corebuild/integration/ILLink.Tasks/ILLink.Tasks.targets b/corebuild/integration/ILLink.Tasks/ILLink.Tasks.targets index 6a4733d7c4e8..43bc5a2c4632 100644 --- a/corebuild/integration/ILLink.Tasks/ILLink.Tasks.targets +++ b/corebuild/integration/ILLink.Tasks/ILLink.Tasks.targets @@ -99,7 +99,7 @@ - + @@ -114,7 +114,7 @@ <_DebugSymbolsIntermediatePath Include="@(_LinkedDebugSymbols)" Condition=" '$(_DebugSymbolsProduced)' == 'true' " /> - + + + + - - <_ReferencedLibraries Include="@(ReferencePath->'%(ResolvedPath)')" Exclude="@(_ManagedAssembliesToLink)" /> + <_ReferencedLibraries Include="@(ReferencePath->'%(ResolvedPath)')" Exclude="@(_ReferencedLibrariesToExclude)" /> <_ManagedAssembliesToLink Include="@(_ReferencedLibraries)" /> + @@ -313,7 +328,7 @@ output and the generated deps.json file. Excluding it from _ManagedResolvedAssembliesToPublish will prevent it from getting filtered out of the publish output later. - + In the future we may want to detect ngen assemblies and filter them more robustly. --> - @@ -437,7 +453,7 @@ <_RemovedNativeDeps Include="@(_NativeResolvedDepsToPublish)" /> <_RemovedNativeDeps Remove="@(_NativeKeptDepsToPublish)" /> - + <_PublishConflictPackageFiles Include="@(_RemovedManagedAssemblies)" /> <_PublishConflictPackageFiles Include="@(_RemovedNativeDeps)" /> From bcd6ed2ed7d076b779491c5e23c8e50a628d468d Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Mon, 26 Feb 2018 17:08:09 -0800 Subject: [PATCH 8/8] Respond to PR feedback --- corebuild/integration/ILLink.Tasks/ILLink.Tasks.targets | 5 ++--- corebuild/integration/test/CommandRunner.cs | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/corebuild/integration/ILLink.Tasks/ILLink.Tasks.targets b/corebuild/integration/ILLink.Tasks/ILLink.Tasks.targets index 43bc5a2c4632..70c051ec28e2 100644 --- a/corebuild/integration/ILLink.Tasks/ILLink.Tasks.targets +++ b/corebuild/integration/ILLink.Tasks/ILLink.Tasks.targets @@ -285,9 +285,8 @@ diff --git a/corebuild/integration/test/CommandRunner.cs b/corebuild/integration/test/CommandRunner.cs index 21ac2a47baf4..efee6cbbd7f0 100644 --- a/corebuild/integration/test/CommandRunner.cs +++ b/corebuild/integration/test/CommandRunner.cs @@ -67,7 +67,7 @@ public int Run(out string commandOutput) RedirectStandardOutput = true, RedirectStandardError = true, }; - outputHelper.WriteLine($"from caller working directory {Environment.CurrentDirectory}"); + outputHelper.WriteLine($"caller working directory: {Environment.CurrentDirectory}"); if (!String.IsNullOrEmpty(args)) { psi.Arguments = args; outputHelper.WriteLine($"{command} {args}");