Merge pull request #2371 from dotnet/pakrym/low-fat
Make desktop publishing "half-portable" by default
This commit is contained in:
commit
482f36d26b
35 changed files with 551 additions and 63 deletions
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
|
||||
namespace DesktopAppWithNativeDep
|
||||
{
|
||||
public static class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"version": "1.0.0-*",
|
||||
"dependencies": {
|
||||
"PackageWithFakeNativeDep": "1.0.0-*",
|
||||
"Microsoft.NETCore.Platforms": "1.0.0-rc2-24008"
|
||||
},
|
||||
"compilationOptions": {
|
||||
"emitEntryPoint": true
|
||||
},
|
||||
"frameworks": {
|
||||
"net451": { }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"version": "1.0.0-*",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0-rc2-20113",
|
||||
"Microsoft.AspNetCore.Hosting": "1.0.0-rc2-20113",
|
||||
"Microsoft.Extensions.Logging.Console": "1.0.0-rc2-20254",
|
||||
"Microsoft.NETCore.Platforms": "1.0.0-rc2-24008"
|
||||
},
|
||||
"compilationOptions": {
|
||||
"emitEntryPoint": true
|
||||
},
|
||||
"compile": [
|
||||
"../src/*.cs"
|
||||
],
|
||||
"frameworks": {
|
||||
"net451": { }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"version": "1.0.0-*",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0-rc2-20113",
|
||||
"Microsoft.AspNetCore.Hosting": "1.0.0-rc2-20113",
|
||||
"Microsoft.Extensions.Logging.Console": "1.0.0-rc2-20254",
|
||||
"Microsoft.NETCore.Platforms": "1.0.0-rc2-24008"
|
||||
},
|
||||
"compilationOptions": {
|
||||
"platform": "anycpu32bitpreferred",
|
||||
"emitEntryPoint": true
|
||||
},
|
||||
"compile": [
|
||||
"../src/*.cs"
|
||||
],
|
||||
"frameworks": {
|
||||
"net451": { }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"version": "1.0.0-*",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0-rc2-20113",
|
||||
"Microsoft.AspNetCore.Hosting": "1.0.0-rc2-20113",
|
||||
"Microsoft.Extensions.Logging.Console": "1.0.0-rc2-20254",
|
||||
"Microsoft.NETCore.Platforms": "1.0.0-rc2-24008"
|
||||
},
|
||||
"compilationOptions": {
|
||||
"emitEntryPoint": true
|
||||
},
|
||||
"compile": [
|
||||
"../src/*.cs"
|
||||
],
|
||||
"frameworks": {
|
||||
"net451": { }
|
||||
},
|
||||
"runtimes": {
|
||||
"win7-x86": {},
|
||||
"win7-x64": {},
|
||||
"osx.10.11-x64": {}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Server.Kestrel;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Filter;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
|
||||
namespace SampleApp
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
private static string Args { get; set; }
|
||||
private static CancellationTokenSource ServerCancellationTokenSource { get; set; }
|
||||
|
||||
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory, IApplicationEnvironment env)
|
||||
{
|
||||
var ksi = app.ServerFeatures.Get<IKestrelServerInformation>();
|
||||
ksi.NoDelay = true;
|
||||
|
||||
loggerFactory.AddConsole(LogLevel.Error);
|
||||
|
||||
app.UseKestrelConnectionLogging();
|
||||
|
||||
app.Run(async context =>
|
||||
{
|
||||
Console.WriteLine("{0} {1}{2}{3}",
|
||||
context.Request.Method,
|
||||
context.Request.PathBase,
|
||||
context.Request.Path,
|
||||
context.Request.QueryString);
|
||||
Console.WriteLine($"Method: {context.Request.Method}");
|
||||
Console.WriteLine($"PathBase: {context.Request.PathBase}");
|
||||
Console.WriteLine($"Path: {context.Request.Path}");
|
||||
Console.WriteLine($"QueryString: {context.Request.QueryString}");
|
||||
|
||||
var connectionFeature = context.Connection;
|
||||
Console.WriteLine($"Peer: {connectionFeature.RemoteIpAddress?.ToString()} {connectionFeature.RemotePort}");
|
||||
Console.WriteLine($"Sock: {connectionFeature.LocalIpAddress?.ToString()} {connectionFeature.LocalPort}");
|
||||
|
||||
var content = $"Hello world!{Environment.NewLine}Received '{Args}' from command line.";
|
||||
context.Response.ContentLength = content.Length;
|
||||
context.Response.ContentType = "text/plain";
|
||||
await context.Response.WriteAsync(content);
|
||||
});
|
||||
}
|
||||
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
if (args.Length == 0)
|
||||
{
|
||||
Console.WriteLine("KestrelHelloWorld <url to host>");
|
||||
return 1;
|
||||
}
|
||||
|
||||
var url = new Uri(args[0]);
|
||||
Args = string.Join(" ", args);
|
||||
|
||||
var host = new WebHostBuilder()
|
||||
.UseServer("Microsoft.AspNetCore.Server.Kestrel")
|
||||
.UseUrls(url.ToString())
|
||||
.UseStartup<Startup>()
|
||||
.Build();
|
||||
|
||||
ServerCancellationTokenSource = new CancellationTokenSource();
|
||||
|
||||
// shutdown server after 20s.
|
||||
var shutdownTask = Task.Run(async () =>
|
||||
{
|
||||
await Task.Delay(20000);
|
||||
ServerCancellationTokenSource.Cancel();
|
||||
});
|
||||
|
||||
host.Run(ServerCancellationTokenSource.Token);
|
||||
shutdownTask.Wait();
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
10
TestAssets/TestPackages/PackageWithFakeNativeDep/Lib.cs
Normal file
10
TestAssets/TestPackages/PackageWithFakeNativeDep/Lib.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
namespace PackageWithFakeNativeDep
|
||||
{
|
||||
public static class Lib
|
||||
{
|
||||
public static string GetMessage()
|
||||
{
|
||||
return "Hello, World";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"version": "1.0.0",
|
||||
"packInclude": {
|
||||
"runtimes/": "runtimes/"
|
||||
},
|
||||
"frameworks": {
|
||||
"net45": {}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
This is just a marker to ensure things are deployed right
|
|
@ -0,0 +1 @@
|
|||
This is just a marker to ensure things are deployed right
|
|
@ -9,9 +9,8 @@
|
|||
<ProjectGuid>c26a48bb-193f-450c-ab09-4d3324c78188</ProjectGuid>
|
||||
<RootNamespace>dotnet-dependency-tool-invoker</RootNamespace>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\..\artifacts\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
|
|
|
@ -9,9 +9,8 @@
|
|||
<ProjectGuid>da8e0e9e-a6d6-4583-864c-8f40465e3a48</ProjectGuid>
|
||||
<RootNamespace>TestAppWithArgs</RootNamespace>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\..\artifacts\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
|
|
|
@ -9,9 +9,8 @@
|
|||
<ProjectGuid>0138cb8f-4aa9-4029-a21e-c07c30f425ba</ProjectGuid>
|
||||
<RootNamespace>TestAppWithContents</RootNamespace>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\..\artifacts\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
|
|
|
@ -25,6 +25,15 @@ namespace Microsoft.DotNet.Cli.Build
|
|||
|
||||
public static readonly dynamic[] Projects = new[]
|
||||
{
|
||||
new
|
||||
{
|
||||
Name = "PackageWithFakeNativeDep",
|
||||
IsTool = false,
|
||||
Path = "TestAssets/TestPackages/PackageWithFakeNativeDep",
|
||||
IsApplicable = new Func<bool>(() => true),
|
||||
VersionSuffix = s_testPackageBuildVersionSuffix,
|
||||
Clean = true
|
||||
},
|
||||
new
|
||||
{
|
||||
Name = "dotnet-dependency-context-test",
|
||||
|
|
|
@ -200,7 +200,6 @@ namespace Microsoft.DotNet.Cli.Build
|
|||
.Execute();
|
||||
}
|
||||
|
||||
|
||||
var projectJson = Path.Combine(fullPath, "project.json");
|
||||
var dotnetPackArgs = new List<string> {
|
||||
projectJson,
|
||||
|
@ -245,7 +244,6 @@ namespace Microsoft.DotNet.Cli.Build
|
|||
Rmdir(Path.Combine(Dirs.NuGetPackages, ".tools", packageProject.Name));
|
||||
}
|
||||
}
|
||||
|
||||
return c.Success();
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ using Microsoft.Extensions.DependencyModel;
|
|||
using NuGet.Frameworks;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using System.Reflection.PortableExecutable;
|
||||
|
||||
namespace Microsoft.Dotnet.Cli.Compiler.Common
|
||||
{
|
||||
|
@ -147,16 +148,10 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common
|
|||
|
||||
private void WriteFramework(JObject runtimeOptions, LibraryExporter exporter)
|
||||
{
|
||||
var redistPackage = _context.RootProject.Dependencies
|
||||
.Where(r => r.Type.Equals(LibraryDependencyType.Platform))
|
||||
.ToList();
|
||||
if (redistPackage.Count > 0)
|
||||
var redistPackage = _context.PlatformLibrary;
|
||||
if (redistPackage != null)
|
||||
{
|
||||
if (redistPackage.Count > 1)
|
||||
{
|
||||
throw new InvalidOperationException("Multiple packages with type: \"platform\" were specified!");
|
||||
}
|
||||
var packageName = redistPackage.Single().Name;
|
||||
var packageName = redistPackage.Identity.Name;
|
||||
|
||||
var redistExport = exporter.GetAllExports()
|
||||
.FirstOrDefault(e => e.Library.Identity.Name.Equals(packageName));
|
||||
|
|
|
@ -20,6 +20,7 @@ namespace Microsoft.DotNet.ProjectModel.Compilation
|
|||
{
|
||||
private readonly string _configuration;
|
||||
private readonly string _runtime;
|
||||
private readonly string[] _runtimeFallbacks;
|
||||
private readonly ProjectDescription _rootProject;
|
||||
private readonly string _buildBasePath;
|
||||
private readonly string _solutionRootPath;
|
||||
|
@ -28,6 +29,7 @@ namespace Microsoft.DotNet.ProjectModel.Compilation
|
|||
LibraryManager manager,
|
||||
string configuration,
|
||||
string runtime,
|
||||
string[] runtimeFallbacks,
|
||||
string buildBasePath,
|
||||
string solutionRootPath)
|
||||
{
|
||||
|
@ -39,6 +41,7 @@ namespace Microsoft.DotNet.ProjectModel.Compilation
|
|||
LibraryManager = manager;
|
||||
_configuration = configuration;
|
||||
_runtime = runtime;
|
||||
_runtimeFallbacks = runtimeFallbacks;
|
||||
_buildBasePath = buildBasePath;
|
||||
_solutionRootPath = solutionRootPath;
|
||||
_rootProject = rootProject;
|
||||
|
@ -96,7 +99,6 @@ namespace Microsoft.DotNet.ProjectModel.Compilation
|
|||
var analyzerReferences = new List<AnalyzerReference>();
|
||||
var libraryExport = GetExport(library);
|
||||
|
||||
|
||||
// We need to filter out source references from non-root libraries,
|
||||
// so we rebuild the library export
|
||||
foreach (var reference in libraryExport.CompilationAssemblies)
|
||||
|
@ -114,12 +116,25 @@ namespace Microsoft.DotNet.ProjectModel.Compilation
|
|||
analyzerReferences.AddRange(libraryExport.AnalyzerReferences);
|
||||
}
|
||||
|
||||
yield return LibraryExportBuilder.Create(library)
|
||||
var builder = LibraryExportBuilder.Create(library);
|
||||
if (_runtime != null && _runtimeFallbacks != null)
|
||||
{
|
||||
// For portable apps that are built with runtime trimming we replace RuntimeAssemblyGroups and NativeLibraryGroups
|
||||
// with single default group that contains asset specific to runtime we are trimming for
|
||||
// based on runtime fallback list
|
||||
builder.WithRuntimeAssemblyGroups(TrimAssetGroups(libraryExport.RuntimeAssemblyGroups, _runtimeFallbacks));
|
||||
builder.WithNativeLibraryGroups(TrimAssetGroups(libraryExport.NativeLibraryGroups, _runtimeFallbacks));
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.WithRuntimeAssemblyGroups(libraryExport.RuntimeAssemblyGroups);
|
||||
builder.WithNativeLibraryGroups(libraryExport.NativeLibraryGroups);
|
||||
}
|
||||
|
||||
yield return builder
|
||||
.WithCompilationAssemblies(compilationAssemblies)
|
||||
.WithSourceReferences(sourceReferences)
|
||||
.WithRuntimeAssemblyGroups(libraryExport.RuntimeAssemblyGroups)
|
||||
.WithRuntimeAssets(libraryExport.RuntimeAssets)
|
||||
.WithNativeLibraryGroups(libraryExport.NativeLibraryGroups)
|
||||
.WithEmbedddedResources(libraryExport.EmbeddedResources)
|
||||
.WithAnalyzerReference(analyzerReferences)
|
||||
.WithResourceAssemblies(libraryExport.ResourceAssemblies)
|
||||
|
@ -127,6 +142,27 @@ namespace Microsoft.DotNet.ProjectModel.Compilation
|
|||
}
|
||||
}
|
||||
|
||||
private IEnumerable<LibraryAssetGroup> TrimAssetGroups(IEnumerable<LibraryAssetGroup> runtimeAssemblyGroups,
|
||||
string[] runtimeFallbacks)
|
||||
{
|
||||
LibraryAssetGroup runtimeAssets;
|
||||
foreach (var rid in runtimeFallbacks)
|
||||
{
|
||||
runtimeAssets = runtimeAssemblyGroups.GetRuntimeGroup(rid);
|
||||
if (runtimeAssets != null)
|
||||
{
|
||||
yield return new LibraryAssetGroup(runtimeAssets.Assets);
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
|
||||
runtimeAssets = runtimeAssemblyGroups.GetDefaultGroup();
|
||||
if (runtimeAssets != null)
|
||||
{
|
||||
yield return runtimeAssets;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a LibraryExport from LibraryDescription.
|
||||
///
|
||||
|
|
|
@ -14,12 +14,18 @@ namespace Microsoft.DotNet.ProjectModel
|
|||
{
|
||||
public class ProjectContext
|
||||
{
|
||||
private string[] _runtimeFallbacks;
|
||||
|
||||
public GlobalSettings GlobalSettings { get; }
|
||||
|
||||
public ProjectDescription RootProject { get; }
|
||||
|
||||
public NuGetFramework TargetFramework { get; }
|
||||
|
||||
public LibraryDescription PlatformLibrary { get; }
|
||||
|
||||
public bool IsPortable { get; }
|
||||
|
||||
public string RuntimeIdentifier { get; }
|
||||
|
||||
public Project ProjectFile => RootProject?.Project;
|
||||
|
@ -37,7 +43,9 @@ namespace Microsoft.DotNet.ProjectModel
|
|||
internal ProjectContext(
|
||||
GlobalSettings globalSettings,
|
||||
ProjectDescription rootProject,
|
||||
LibraryDescription platformLibrary,
|
||||
NuGetFramework targetFramework,
|
||||
bool isPortable,
|
||||
string runtimeIdentifier,
|
||||
string packagesDirectory,
|
||||
LibraryManager libraryManager,
|
||||
|
@ -45,16 +53,29 @@ namespace Microsoft.DotNet.ProjectModel
|
|||
{
|
||||
GlobalSettings = globalSettings;
|
||||
RootProject = rootProject;
|
||||
PlatformLibrary = platformLibrary;
|
||||
TargetFramework = targetFramework;
|
||||
RuntimeIdentifier = runtimeIdentifier;
|
||||
PackagesDirectory = packagesDirectory;
|
||||
LibraryManager = libraryManager;
|
||||
LockFile = lockfile;
|
||||
IsPortable = isPortable;
|
||||
}
|
||||
|
||||
public LibraryExporter CreateExporter(string configuration, string buildBasePath = null)
|
||||
{
|
||||
return new LibraryExporter(RootProject, LibraryManager, configuration, RuntimeIdentifier, buildBasePath, RootDirectory);
|
||||
if (IsPortable && RuntimeIdentifier != null && _runtimeFallbacks == null)
|
||||
{
|
||||
var graph = RuntimeGraphCollector.Collect(LibraryManager.GetLibraries());
|
||||
_runtimeFallbacks = graph.ExpandRuntime(RuntimeIdentifier).ToArray();
|
||||
}
|
||||
return new LibraryExporter(RootProject,
|
||||
LibraryManager,
|
||||
configuration,
|
||||
RuntimeIdentifier,
|
||||
_runtimeFallbacks,
|
||||
buildBasePath,
|
||||
RootDirectory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -146,15 +167,12 @@ namespace Microsoft.DotNet.ProjectModel
|
|||
return this;
|
||||
}
|
||||
|
||||
var standalone = !RootProject.Dependencies
|
||||
.Any(d => d.Type.Equals(LibraryDependencyType.Platform));
|
||||
|
||||
var context = CreateBuilder(ProjectFile.ProjectFilePath, TargetFramework)
|
||||
.WithRuntimeIdentifiers(standalone ? runtimeIdentifiers : Enumerable.Empty<string>())
|
||||
.WithRuntimeIdentifiers(runtimeIdentifiers)
|
||||
.WithLockFile(LockFile)
|
||||
.Build();
|
||||
|
||||
if (standalone && context.RuntimeIdentifier == null)
|
||||
if (!context.IsPortable && context.RuntimeIdentifier == null)
|
||||
{
|
||||
// We are standalone, but don't support this runtime
|
||||
var rids = string.Join(", ", runtimeIdentifiers);
|
||||
|
|
|
@ -9,6 +9,7 @@ using System.Text;
|
|||
using Microsoft.DotNet.ProjectModel.Graph;
|
||||
using Microsoft.DotNet.ProjectModel.Resolution;
|
||||
using Microsoft.Extensions.Internal;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
using NuGet.Frameworks;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectModel
|
||||
|
@ -32,7 +33,7 @@ namespace Microsoft.DotNet.ProjectModel
|
|||
private string PackagesDirectory { get; set; }
|
||||
|
||||
private string ReferenceAssembliesPath { get; set; }
|
||||
|
||||
|
||||
private bool IsDesignTime { get; set; }
|
||||
|
||||
private Func<string, Project> ProjectResolver { get; set; }
|
||||
|
@ -118,7 +119,7 @@ namespace Microsoft.DotNet.ProjectModel
|
|||
Settings = settings;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public ProjectContextBuilder AsDesignTime()
|
||||
{
|
||||
IsDesignTime = true;
|
||||
|
@ -197,18 +198,53 @@ namespace Microsoft.DotNet.ProjectModel
|
|||
libraries.Add(new LibraryKey(mainProject.Identity.Name), mainProject);
|
||||
}
|
||||
|
||||
LibraryRange? platformDependency = null;
|
||||
if (mainProject != null)
|
||||
{
|
||||
platformDependency = mainProject.Dependencies
|
||||
.Where(d => d.Type.Equals(LibraryDependencyType.Platform))
|
||||
.Cast<LibraryRange?>()
|
||||
.FirstOrDefault();
|
||||
}
|
||||
bool isPortable = platformDependency != null || TargetFramework.IsDesktop();
|
||||
|
||||
LockFileTarget target = null;
|
||||
LibraryDescription platformLibrary = null;
|
||||
|
||||
if (lockFileLookup != null)
|
||||
{
|
||||
target = SelectTarget(LockFile);
|
||||
target = SelectTarget(LockFile, isPortable);
|
||||
if (target != null)
|
||||
{
|
||||
var nugetPackageResolver = new PackageDependencyProvider(PackagesDirectory, frameworkReferenceResolver);
|
||||
var msbuildProjectResolver = new MSBuildDependencyProvider(Project, ProjectResolver);
|
||||
ScanLibraries(target, lockFileLookup, libraries, msbuildProjectResolver, nugetPackageResolver, projectResolver);
|
||||
|
||||
if (platformDependency != null)
|
||||
{
|
||||
platformLibrary = libraries[new LibraryKey(platformDependency.Value.Name)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string runtime;
|
||||
if (TargetFramework.IsDesktop())
|
||||
{
|
||||
var legacyRuntime = PlatformServices.Default.Runtime.GetLegacyRestoreRuntimeIdentifier();
|
||||
if (RuntimeIdentifiers.Contains(legacyRuntime))
|
||||
{
|
||||
runtime = legacyRuntime;
|
||||
}
|
||||
else
|
||||
{
|
||||
runtime = RuntimeIdentifiers.FirstOrDefault();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
runtime = target?.RuntimeIdentifier;
|
||||
}
|
||||
|
||||
var referenceAssemblyDependencyResolver = new ReferenceAssemblyDependencyResolver(frameworkReferenceResolver);
|
||||
bool requiresFrameworkAssemblies;
|
||||
|
||||
|
@ -272,8 +308,10 @@ namespace Microsoft.DotNet.ProjectModel
|
|||
return new ProjectContext(
|
||||
GlobalSettings,
|
||||
mainProject,
|
||||
platformLibrary,
|
||||
TargetFramework,
|
||||
target?.RuntimeIdentifier,
|
||||
isPortable,
|
||||
runtime,
|
||||
PackagesDirectory,
|
||||
libraryManager,
|
||||
LockFile);
|
||||
|
@ -454,15 +492,18 @@ namespace Microsoft.DotNet.ProjectModel
|
|||
}
|
||||
}
|
||||
|
||||
private LockFileTarget SelectTarget(LockFile lockFile)
|
||||
private LockFileTarget SelectTarget(LockFile lockFile, bool isPortable)
|
||||
{
|
||||
foreach (var runtimeIdentifier in RuntimeIdentifiers)
|
||||
if (!isPortable)
|
||||
{
|
||||
foreach (var scanTarget in lockFile.Targets)
|
||||
foreach (var runtimeIdentifier in RuntimeIdentifiers)
|
||||
{
|
||||
if (Equals(scanTarget.TargetFramework, TargetFramework) && string.Equals(scanTarget.RuntimeIdentifier, runtimeIdentifier, StringComparison.Ordinal))
|
||||
foreach (var scanTarget in lockFile.Targets)
|
||||
{
|
||||
return scanTarget;
|
||||
if (Equals(scanTarget.TargetFramework, TargetFramework) && string.Equals(scanTarget.RuntimeIdentifier, runtimeIdentifier, StringComparison.Ordinal))
|
||||
{
|
||||
return scanTarget;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
34
src/Microsoft.DotNet.ProjectModel/RuntimeGraphCollector.cs
Normal file
34
src/Microsoft.DotNet.ProjectModel/RuntimeGraphCollector.cs
Normal file
|
@ -0,0 +1,34 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.DotNet.ProjectModel.Graph;
|
||||
using NuGet.RuntimeModel;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectModel
|
||||
{
|
||||
class RuntimeGraphCollector
|
||||
{
|
||||
private const string RuntimeJsonFileName = "runtime.json";
|
||||
|
||||
public static RuntimeGraph Collect(IEnumerable<LibraryDescription> libraries)
|
||||
{
|
||||
var graph = RuntimeGraph.Empty;
|
||||
foreach (var library in libraries)
|
||||
{
|
||||
if (library.Identity.Type == LibraryType.Package)
|
||||
{
|
||||
var runtimeJson = ((PackageDescription)library).PackageLibrary.Files.FirstOrDefault(f => f == RuntimeJsonFileName);
|
||||
if (runtimeJson != null)
|
||||
{
|
||||
var runtimeJsonFullName = Path.Combine(library.Path, runtimeJson);
|
||||
graph = RuntimeGraph.Merge(graph, JsonRuntimeFormat.ReadRuntimeGraph(runtimeJsonFullName));
|
||||
}
|
||||
}
|
||||
}
|
||||
return graph;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@
|
|||
},
|
||||
"Newtonsoft.Json": "7.0.1",
|
||||
"NuGet.Packaging": "3.5.0-beta-1130",
|
||||
"NuGet.RuntimeModel": "3.5.0-beta-1130",
|
||||
"System.Reflection.Metadata": "1.3.0-rc2-24008"
|
||||
},
|
||||
"frameworks": {
|
||||
|
|
|
@ -44,9 +44,9 @@ namespace Microsoft.DotNet.TestFramework
|
|||
.Where(dir =>
|
||||
{
|
||||
dir = dir.ToLower();
|
||||
return !dir.EndsWith($"{Path.DirectorySeparatorChar}bin")
|
||||
return !dir.EndsWith($"{Path.DirectorySeparatorChar}bin")
|
||||
&& !dir.Contains($"{Path.DirectorySeparatorChar}bin{Path.DirectorySeparatorChar}")
|
||||
&& !dir.EndsWith($"{Path.DirectorySeparatorChar}obj")
|
||||
&& !dir.EndsWith($"{Path.DirectorySeparatorChar}obj")
|
||||
&& !dir.Contains($"{Path.DirectorySeparatorChar}obj{Path.DirectorySeparatorChar}");
|
||||
});
|
||||
|
||||
|
|
|
@ -108,10 +108,10 @@ namespace Microsoft.DotNet.Tools.Build
|
|||
{
|
||||
if (CLIChangedSinceLastCompilation(project))
|
||||
{
|
||||
Reporter.Output.WriteLine($"Project {project.GetDisplayName()} will be compiled because the CLI changed");
|
||||
Reporter.Output.WriteLine($"Project {project.GetDisplayName()} will be compiled because the version or bitness of the CLI changed since the last build");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
var compilerIO = GetCompileIO(project, dependencies);
|
||||
|
||||
// rebuild if empty inputs / outputs
|
||||
|
@ -189,7 +189,7 @@ namespace Microsoft.DotNet.Tools.Build
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private bool CLIChangedSinceLastCompilation(ProjectContext project)
|
||||
{
|
||||
var currentVersionFile = DotnetFiles.VersionFile;
|
||||
|
@ -207,7 +207,9 @@ namespace Microsoft.DotNet.Tools.Build
|
|||
return false;
|
||||
}
|
||||
|
||||
var versionsAreEqual = string.Equals(File.ReadAllText(currentVersionFile), File.ReadAllText(versionFileFromLastCompile), StringComparison.OrdinalIgnoreCase);
|
||||
var currentContent = ComputeCurrentVersionFileData();
|
||||
|
||||
var versionsAreEqual = string.Equals(currentContent, File.ReadAllText(versionFileFromLastCompile), StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
return !versionsAreEqual;
|
||||
}
|
||||
|
@ -216,7 +218,7 @@ namespace Microsoft.DotNet.Tools.Build
|
|||
{
|
||||
if (File.Exists(DotnetFiles.VersionFile))
|
||||
{
|
||||
var projectVersionFile = project.GetSDKVersionFile(_args.ConfigValue, _args.BuildBasePathValue,_args.OutputValue);
|
||||
var projectVersionFile = project.GetSDKVersionFile(_args.ConfigValue, _args.BuildBasePathValue, _args.OutputValue);
|
||||
var parentDirectory = Path.GetDirectoryName(projectVersionFile);
|
||||
|
||||
if (!Directory.Exists(parentDirectory))
|
||||
|
@ -224,7 +226,9 @@ namespace Microsoft.DotNet.Tools.Build
|
|||
Directory.CreateDirectory(parentDirectory);
|
||||
}
|
||||
|
||||
File.Copy(DotnetFiles.VersionFile, projectVersionFile, true);
|
||||
string content = ComputeCurrentVersionFileData();
|
||||
|
||||
File.WriteAllText(projectVersionFile, content);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -232,6 +236,14 @@ namespace Microsoft.DotNet.Tools.Build
|
|||
}
|
||||
}
|
||||
|
||||
private static string ComputeCurrentVersionFileData()
|
||||
{
|
||||
var content = File.ReadAllText(DotnetFiles.VersionFile);
|
||||
content += Environment.NewLine;
|
||||
content += PlatformServices.Default.Runtime.GetRuntimeIdentifier();
|
||||
return content;
|
||||
}
|
||||
|
||||
private void PrintSummary(bool success)
|
||||
{
|
||||
// todo: Ideally it's the builder's responsibility for adding the time elapsed. That way we avoid cross cutting display concerns between compile and build for printing time elapsed
|
||||
|
|
|
@ -5,11 +5,13 @@ using System.Collections.Generic;
|
|||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.DotNet.Cli.Compiler.Common;
|
||||
using Microsoft.DotNet.Cli.Utils;
|
||||
using Microsoft.DotNet.ProjectModel;
|
||||
using Microsoft.DotNet.ProjectModel.Compilation;
|
||||
using Microsoft.Extensions.DependencyModel;
|
||||
using NuGet.Frameworks;
|
||||
|
||||
namespace Microsoft.DotNet.Tools.Compiler
|
||||
{
|
||||
|
@ -77,6 +79,15 @@ namespace Microsoft.DotNet.Tools.Compiler
|
|||
};
|
||||
|
||||
var compilationOptions = context.ResolveCompilationOptions(args.ConfigValue);
|
||||
|
||||
// Set default platform if it isn't already set and we're on desktop
|
||||
if(compilationOptions.EmitEntryPoint == true && string.IsNullOrEmpty(compilationOptions.Platform) && context.TargetFramework.IsDesktop())
|
||||
{
|
||||
// See https://github.com/dotnet/cli/issues/2428 for more details.
|
||||
compilationOptions.Platform = RuntimeInformation.ProcessArchitecture == Architecture.X64 ?
|
||||
"x64" : "anycpu32bitpreferred";
|
||||
}
|
||||
|
||||
var languageId = CompilerUtil.ResolveLanguageId(context);
|
||||
|
||||
var references = new List<string>();
|
||||
|
|
|
@ -128,21 +128,19 @@ namespace Microsoft.DotNet.Tools.Publish
|
|||
// Use a library exporter to collect publish assets
|
||||
var exporter = context.CreateExporter(configuration, buildBasePath);
|
||||
|
||||
var isPortable = string.IsNullOrEmpty(context.RuntimeIdentifier);
|
||||
|
||||
// Collect all exports and organize them
|
||||
var packageExports = exporter.GetAllExports()
|
||||
.Where(e => e.Library.Identity.Type.Equals(LibraryType.Package))
|
||||
.ToDictionary(e => e.Library.Identity.Name);
|
||||
var collectExclusionList = isPortable ? GetExclusionList(context, packageExports) : new HashSet<string>();
|
||||
var collectExclusionList = context.IsPortable ? GetExclusionList(context, packageExports) : new HashSet<string>();
|
||||
|
||||
var exports = exporter.GetAllExports();
|
||||
foreach (var export in exports.Where(e => !collectExclusionList.Contains(e.Library.Identity.Name)))
|
||||
{
|
||||
Reporter.Verbose.WriteLine($"publish: Publishing {export.Library.Identity.ToString().Green().Bold()} ...");
|
||||
|
||||
PublishAssetGroups(export.RuntimeAssemblyGroups, outputPath, nativeSubdirectories: false, includeRuntimeGroups: isPortable);
|
||||
PublishAssetGroups(export.NativeLibraryGroups, outputPath, nativeSubdirectories, includeRuntimeGroups: isPortable);
|
||||
PublishAssetGroups(export.RuntimeAssemblyGroups, outputPath, nativeSubdirectories: false, includeRuntimeGroups: context.IsPortable);
|
||||
PublishAssetGroups(export.NativeLibraryGroups, outputPath, nativeSubdirectories, includeRuntimeGroups: context.IsPortable);
|
||||
}
|
||||
|
||||
if (options.PreserveCompilationContext.GetValueOrDefault())
|
||||
|
@ -152,7 +150,7 @@ namespace Microsoft.DotNet.Tools.Publish
|
|||
PublishRefs(export, outputPath, !collectExclusionList.Contains(export.Library.Identity.Name));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var buildOutputPaths = context.GetOutputPaths(configuration, buildBasePath, null);
|
||||
PublishBuildOutputFiles(buildOutputPaths, context, outputPath, Configuration);
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<ProjectGuid>0B31C336-149D-471A-B7B1-27B0F1E80F83</ProjectGuid>
|
||||
<RootNamespace>Microsoft.DotNet.Cli.Msi.Tests</RootNamespace>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\..\artifacts\</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
|
|
|
@ -328,7 +328,7 @@ namespace Microsoft.DotNet.ProjectModel.Tests
|
|||
}
|
||||
|
||||
var libraryManager = new LibraryManager(new[] { description }, new DiagnosticMessage[] { }, "");
|
||||
var allExports = new LibraryExporter(rootProjectDescription, libraryManager, "config", "runtime", "basepath", "solutionroot").GetAllExports();
|
||||
var allExports = new LibraryExporter(rootProjectDescription, libraryManager, "config", "runtime", null, "basepath", "solutionroot").GetAllExports();
|
||||
var export = allExports.Single();
|
||||
return export;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ using Microsoft.Extensions.PlatformAbstractions;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.DotNet.Tools.Test.Utilities
|
||||
{
|
||||
|
@ -42,6 +43,12 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
|
|||
_buidBasePathDirectory = buildBasePath;
|
||||
}
|
||||
|
||||
public override Task<CommandResult> ExecuteAsync(string args = "")
|
||||
{
|
||||
args = $"publish {BuildArgs()} {args}";
|
||||
return base.ExecuteAsync(args);
|
||||
}
|
||||
|
||||
public override CommandResult Execute(string args = "")
|
||||
{
|
||||
args = $"publish {BuildArgs()} {args}";
|
||||
|
|
|
@ -16,4 +16,15 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class WindowsOnlyTheoryAttribute : TheoryAttribute
|
||||
{
|
||||
public WindowsOnlyTheoryAttribute()
|
||||
{
|
||||
if (PlatformServices.Default.Runtime.OperatingSystemPlatform != Platform.Windows)
|
||||
{
|
||||
this.Skip = "This test requires windows to run";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
129
test/dotnet-publish.Tests/PublishDesktopTests.cs
Normal file
129
test/dotnet-publish.Tests/PublishDesktopTests.cs
Normal file
|
@ -0,0 +1,129 @@
|
|||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using FluentAssertions;
|
||||
using Microsoft.DotNet.Cli.Utils;
|
||||
using Microsoft.DotNet.TestFramework;
|
||||
using Microsoft.DotNet.Tools.Test.Utilities;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.DotNet.Tools.Publish.Tests
|
||||
{
|
||||
public class PublishDesktopTests : TestBase
|
||||
{
|
||||
[WindowsOnlyTheory]
|
||||
[InlineData(null, null)]
|
||||
[InlineData("win7-x64", "the-win-x64-version.txt")]
|
||||
[InlineData("win7-x86", "the-win-x86-version.txt")]
|
||||
public async Task DesktopApp_WithDependencyOnNativePackage_ProducesExpectedOutput(string runtime, string expectedOutputName)
|
||||
{
|
||||
if(string.IsNullOrEmpty(expectedOutputName))
|
||||
{
|
||||
expectedOutputName = $"the-win-{RuntimeInformation.ProcessArchitecture.ToString().ToLowerInvariant()}-version.txt";
|
||||
}
|
||||
|
||||
var testInstance = TestAssetsManager.CreateTestInstance(Path.Combine("..", "DesktopTestProjects", "DesktopAppWithNativeDep"))
|
||||
.WithLockFiles();
|
||||
|
||||
var publishCommand = new PublishCommand(testInstance.TestRoot, runtime: runtime);
|
||||
var result = await publishCommand.ExecuteAsync();
|
||||
|
||||
result.Should().Pass();
|
||||
|
||||
// Test the output
|
||||
var outputDir = publishCommand.GetOutputDirectory(portable: false);
|
||||
outputDir.Should().HaveFile(expectedOutputName);
|
||||
outputDir.Should().HaveFile(publishCommand.GetOutputExecutable());
|
||||
}
|
||||
|
||||
[WindowsOnlyTheory]
|
||||
[InlineData("KestrelDesktopWithRuntimes", "http://localhost:20201", null, "libuv.dll", false)]
|
||||
[InlineData("KestrelDesktopWithRuntimes", "http://localhost:20202", "win7-x64", "libuv.dll", false)]
|
||||
[InlineData("KestrelDesktopWithRuntimes", "http://localhost:20203", "win7-x86", "libuv.dll", false)]
|
||||
[InlineData("KestrelDesktopForce32", "http://localhost:20204", "win7-x86", "libuv.dll", true)]
|
||||
[InlineData("KestrelDesktop", "http://localhost:20205", null, "libuv.dll", false)]
|
||||
[InlineData("KestrelDesktop", "http://localhost:20206", "win7-x64", "libuv.dll", false)]
|
||||
[InlineData("KestrelDesktop", "http://localhost:20207", "win7-x86", "libuv.dll", false)]
|
||||
public async Task DesktopApp_WithKestrel_WorksWhenPublished(string project, string url, string runtime, string libuvName, bool forceRunnable)
|
||||
{
|
||||
var runnable = forceRunnable || string.IsNullOrEmpty(runtime) || (PlatformServices.Default.Runtime.GetLegacyRestoreRuntimeIdentifier().Contains(runtime));
|
||||
|
||||
var testInstance = GetTestInstance()
|
||||
.WithLockFiles();
|
||||
|
||||
var publishCommand = new PublishCommand(Path.Combine(testInstance.TestRoot, project), runtime: runtime);
|
||||
var result = await publishCommand.ExecuteAsync();
|
||||
|
||||
result.Should().Pass();
|
||||
|
||||
// Test the output
|
||||
var outputDir = publishCommand.GetOutputDirectory(portable: false);
|
||||
outputDir.Should().HaveFile(libuvName);
|
||||
outputDir.Should().HaveFile(publishCommand.GetOutputExecutable());
|
||||
|
||||
Task exec = null;
|
||||
if (runnable)
|
||||
{
|
||||
var outputExePath = Path.Combine(outputDir.FullName, publishCommand.GetOutputExecutable());
|
||||
|
||||
var command = new TestCommand(outputExePath);
|
||||
try
|
||||
{
|
||||
exec = command.ExecuteAsync(url);
|
||||
NetworkHelper.IsServerUp(url).Should().BeTrue($"Unable to connect to kestrel server - {project} @ {url}");
|
||||
NetworkHelper.TestGetRequest(url, url);
|
||||
}
|
||||
finally
|
||||
{
|
||||
command.KillTree();
|
||||
}
|
||||
if (exec != null)
|
||||
{
|
||||
await exec;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[WindowsOnlyTheory]
|
||||
[InlineData("KestrelDesktop", "http://localhost:20301")]
|
||||
[InlineData("KestrelDesktopWithRuntimes", "http://localhost:20302")]
|
||||
public async Task DesktopApp_WithKestrel_WorksWhenRun(string project, string url)
|
||||
{
|
||||
// Disabled due to https://github.com/dotnet/cli/issues/2428
|
||||
if (RuntimeInformation.ProcessArchitecture == Architecture.X86)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var testInstance = GetTestInstance()
|
||||
.WithLockFiles()
|
||||
.WithBuildArtifacts();
|
||||
|
||||
Task exec = null;
|
||||
var command = new RunCommand(Path.Combine(testInstance.TestRoot, project));
|
||||
try
|
||||
{
|
||||
exec = command.ExecuteAsync(url);
|
||||
NetworkHelper.IsServerUp(url).Should().BeTrue($"Unable to connect to kestrel server - {project} @ {url}");
|
||||
NetworkHelper.TestGetRequest(url, url);
|
||||
}
|
||||
finally
|
||||
{
|
||||
command.KillTree();
|
||||
}
|
||||
if (exec != null)
|
||||
{
|
||||
await exec;
|
||||
}
|
||||
}
|
||||
|
||||
private static TestInstance GetTestInstance([CallerMemberName] string callingMethod = "")
|
||||
{
|
||||
return TestAssetsManager.CreateTestInstance(Path.Combine("..", "DesktopTestProjects", "DesktopKestrelSample"), callingMethod);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,21 +10,19 @@
|
|||
"Microsoft.DotNet.Tools.Tests.Utilities": {
|
||||
"target": "project"
|
||||
},
|
||||
"Microsoft.DotNet.Cli.Utils": {
|
||||
"target": "project"
|
||||
},
|
||||
"xunit": "2.1.0",
|
||||
"xunit.netcore.extensions": "1.0.0-prerelease-00206",
|
||||
"dotnet-test-xunit": "1.0.0-dev-140469-38"
|
||||
"dotnet-test-xunit": "1.0.0-dev-140469-38",
|
||||
"System.Runtime.InteropServices.RuntimeInformation": "4.0.0-rc2-24008"
|
||||
},
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
"imports": [
|
||||
"netstandardapp1.5",
|
||||
"dnxcore50",
|
||||
"portable-net45+win8"
|
||||
]
|
||||
}
|
||||
"netcoreapp1.0": {
|
||||
"imports": [
|
||||
"netstandardapp1.5",
|
||||
"dnxcore50",
|
||||
"portable-net45+win8"
|
||||
]
|
||||
}
|
||||
},
|
||||
"testRunner": "xunit"
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue