diff --git a/NuGet.Config b/NuGet.Config index afae6d86d..a8993ec6d 100644 --- a/NuGet.Config +++ b/NuGet.Config @@ -9,8 +9,4 @@ - - - - diff --git a/TestAssets/TestPackages/dotnet-portable/project.json b/TestAssets/TestPackages/dotnet-portable/project.json index 0f9d20ba9..6e79060d4 100644 --- a/TestAssets/TestPackages/dotnet-portable/project.json +++ b/TestAssets/TestPackages/dotnet-portable/project.json @@ -11,7 +11,7 @@ "portable-net45+win8" ], "dependencies": { - "Microsoft.NETCore.App": "1.0.0-rc2-23911" + "Microsoft.NETCore.App": { "type": "platform", "version": "1.0.0-rc2-23911" } } } } diff --git a/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/Validator.cs b/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/Validator.cs index 0cfe83ce7..7fd657a92 100644 --- a/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/Validator.cs +++ b/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/Validator.cs @@ -5,6 +5,7 @@ using System; using System.IO; using System.Linq; using System.Reflection; +using System.Collections.Generic; namespace Microsoft.Extensions.DependencyModel { @@ -54,12 +55,12 @@ namespace Microsoft.Extensions.DependencyModel foreach (var runtimeLibrary in context.RuntimeLibraries) { CheckMetadata(runtimeLibrary); - foreach (var runtimeAssembly in runtimeLibrary.Assemblies) - { - var assembly = Assembly.Load(runtimeAssembly.Name); - } } + foreach (var name in context.GetDefaultAssemblyNames()) + { + var assembly = Assembly.Load(new AssemblyName(name)); + } } } } diff --git a/TestAssets/TestProjects/PortableTests/PortableApp/project.json b/TestAssets/TestProjects/PortableTests/PortableApp/project.json index 3111191ad..5a5cd38cf 100644 --- a/TestAssets/TestProjects/PortableTests/PortableApp/project.json +++ b/TestAssets/TestProjects/PortableTests/PortableApp/project.json @@ -10,7 +10,7 @@ "portable-net45+win8" ], "dependencies": { - "Microsoft.NETCore.App": "1.0.0-rc2-23911" + "Microsoft.NETCore.App": { "type": "platform", "version": "1.0.0-rc2-23911" } } } } diff --git a/TestAssets/TestProjects/PortableTests/PortableAppWithNative/project.json b/TestAssets/TestProjects/PortableTests/PortableAppWithNative/project.json index b315d44e7..48de1d5ff 100644 --- a/TestAssets/TestProjects/PortableTests/PortableAppWithNative/project.json +++ b/TestAssets/TestProjects/PortableTests/PortableAppWithNative/project.json @@ -6,7 +6,7 @@ "netstandard1.5": { "imports": [ "dnxcore50", "portable-net45+win8" ], "dependencies": { - "Microsoft.NETCore.App": "1.0.0-rc2-23911", + "Microsoft.NETCore.App": { "type": "platform", "version": "1.0.0-rc2-23911" }, "Microsoft.AspNetCore.Server.Kestrel": "1.0.0-*" } } diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildContext.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildContext.cs index acd500f51..b80196c8c 100644 --- a/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildContext.cs +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildContext.cs @@ -99,7 +99,7 @@ namespace Microsoft.DotNet.Cli.Build.Framework { if (target == null) { - throw new ArgumentNullException("target"); + throw new ArgumentNullException(nameof(target)); } if (target.Conditions == null) @@ -122,7 +122,7 @@ namespace Microsoft.DotNet.Cli.Build.Framework { if (target == null) { - throw new ArgumentNullException("target"); + throw new ArgumentNullException(nameof(target)); } var sectionName = $"{target.Name.PadRight(_maxTargetLen + 2).Yellow()} ({target.Source.White()})"; diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/BuildArchitecturesAttribute.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/BuildArchitecturesAttribute.cs index b166dd36f..da2f99461 100644 --- a/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/BuildArchitecturesAttribute.cs +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/BuildArchitecturesAttribute.cs @@ -12,7 +12,7 @@ namespace Microsoft.DotNet.Cli.Build.Framework { if (architectures == null) { - throw new ArgumentNullException("architectures"); + throw new ArgumentNullException(nameof(architectures)); } _buildArchitectures = architectures; diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/BuildPlatformsAttribute.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/BuildPlatformsAttribute.cs index 92e8f2441..28c934a6f 100644 --- a/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/BuildPlatformsAttribute.cs +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/BuildPlatformsAttribute.cs @@ -12,7 +12,7 @@ namespace Microsoft.DotNet.Cli.Build.Framework { if (platforms == null) { - throw new ArgumentNullException("platforms"); + throw new ArgumentNullException(nameof(platforms)); } _buildPlatforms = platforms; diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/AbstractPathBasedCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/AbstractPathBasedCommandResolver.cs index 73167305d..3ac3ce450 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/AbstractPathBasedCommandResolver.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/AbstractPathBasedCommandResolver.cs @@ -15,17 +15,17 @@ namespace Microsoft.DotNet.Cli.Utils protected IEnvironmentProvider _environment; protected IPlatformCommandSpecFactory _commandSpecFactory; - public AbstractPathBasedCommandResolver(IEnvironmentProvider environment, + public AbstractPathBasedCommandResolver(IEnvironmentProvider environment, IPlatformCommandSpecFactory commandSpecFactory) { if (environment == null) { - throw new ArgumentNullException("environment"); + throw new ArgumentNullException(nameof(environment)); } if (commandSpecFactory == null) { - throw new ArgumentNullException("commandSpecFactory"); + throw new ArgumentNullException(nameof(commandSpecFactory)); } _environment = environment; diff --git a/src/Microsoft.DotNet.Cli.Utils/project.json b/src/Microsoft.DotNet.Cli.Utils/project.json index e6cdae2f9..37b17014d 100644 --- a/src/Microsoft.DotNet.Cli.Utils/project.json +++ b/src/Microsoft.DotNet.Cli.Utils/project.json @@ -7,10 +7,10 @@ "dependencies": { "Microsoft.DotNet.ProjectModel": "1.0.0-*", "Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-16537", - "NuGet.Versioning": "3.4.0-rtm-0763", - "NuGet.Packaging": "3.4.0-rtm-0763", - "NuGet.Frameworks": "3.4.0-rtm-0763", - "NuGet.ProjectModel": "3.4.0-rtm-0763" + "NuGet.Versioning": "3.5.0-beta-1034", + "NuGet.Packaging": "3.5.0-beta-1034", + "NuGet.Frameworks": "3.5.0-beta-1034", + "NuGet.ProjectModel": "3.5.0-beta-1034" }, "frameworks": { "net451": { diff --git a/src/Microsoft.DotNet.Compiler.Common/BindingRedirectGenerator.cs b/src/Microsoft.DotNet.Compiler.Common/BindingRedirectGenerator.cs index a8477c5ee..71472b478 100644 --- a/src/Microsoft.DotNet.Compiler.Common/BindingRedirectGenerator.cs +++ b/src/Microsoft.DotNet.Compiler.Common/BindingRedirectGenerator.cs @@ -109,7 +109,11 @@ namespace Microsoft.DotNet.Cli.Compiler.Common private static AssemblyRedirect[] CollectRedirects(IEnumerable dependencies) { - var allRuntimeAssemblies = dependencies.SelectMany(d => d.RuntimeAssemblies).Select(GetAssemblyInfo).ToArray(); + var allRuntimeAssemblies = dependencies + .SelectMany(d => d.RuntimeAssemblyGroups.GetDefaultAssets()) + .Select(GetAssemblyInfo) + .ToArray(); + var assemblyLookup = allRuntimeAssemblies.ToDictionary(r => r.Identity.ToLookupKey()); var redirectAssemblies = new HashSet(); diff --git a/src/Microsoft.DotNet.Compiler.Common/Executable.cs b/src/Microsoft.DotNet.Compiler.Common/Executable.cs index 930450049..e50162b04 100644 --- a/src/Microsoft.DotNet.Compiler.Common/Executable.cs +++ b/src/Microsoft.DotNet.Compiler.Common/Executable.cs @@ -21,9 +21,6 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common { public class Executable { - // GROOOOOSS - private static readonly string RedistPackageName = "Microsoft.NETCore.App"; - private readonly ProjectContext _context; private readonly LibraryExporter _exporter; @@ -94,8 +91,8 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common { foreach (var libraryExport in libraryExports) { - libraryExport.RuntimeAssemblies.CopyTo(_runtimeOutputPath); - libraryExport.NativeLibraries.CopyTo(_runtimeOutputPath); + libraryExport.RuntimeAssemblyGroups.GetDefaultAssets().CopyTo(_runtimeOutputPath); + libraryExport.NativeLibraryGroups.GetDefaultAssets().CopyTo(_runtimeOutputPath); } } @@ -133,15 +130,30 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common var runtimeOptions = new JObject(); json.Add("runtimeOptions", runtimeOptions); - var redistExport = exporter - .GetAllExports() - .FirstOrDefault(l => l.Library.Identity.Name.Equals(RedistPackageName, StringComparison.OrdinalIgnoreCase)); - if (redistExport != null) + var redistPackage = _context.RootProject.Dependencies + .Where(r => r.Type.Equals(LibraryDependencyType.Platform)) + .ToList(); + if(redistPackage.Count > 0) { - var framework = new JObject( - new JProperty("name", redistExport.Library.Identity.Name), - new JProperty("version", redistExport.Library.Identity.Version.ToNormalizedString())); - runtimeOptions.Add("framework", framework); + if(redistPackage.Count > 1) + { + throw new InvalidOperationException("Multiple packages with type: \"platform\" were specified!"); + } + var packageName = redistPackage.Single().Name; + + var redistExport = exporter.GetAllExports() + .FirstOrDefault(e => e.Library.Identity.Name.Equals(packageName)); + if (redistExport == null) + { + throw new InvalidOperationException($"Platform package '{packageName}' was not present in the graph."); + } + else + { + var framework = new JObject( + new JProperty("name", redistExport.Library.Identity.Name), + new JProperty("version", redistExport.Library.Identity.Version.ToNormalizedString())); + runtimeOptions.Add("framework", framework); + } } var runtimeConfigJsonFile = @@ -214,8 +226,8 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common private static IEnumerable GenerateLines(LibraryExport export) { - return GenerateLines(export, export.RuntimeAssemblies, "runtime") - .Union(GenerateLines(export, export.NativeLibraries, "native")); + return GenerateLines(export, export.RuntimeAssemblyGroups.GetDefaultAssets(), "runtime") + .Union(GenerateLines(export, export.NativeLibraryGroups.GetDefaultAssets(), "native")); } private static IEnumerable GenerateLines(LibraryExport export, IEnumerable items, string type) diff --git a/src/Microsoft.DotNet.Compiler.Common/project.json b/src/Microsoft.DotNet.Compiler.Common/project.json index f0376403a..9a885ff0e 100644 --- a/src/Microsoft.DotNet.Compiler.Common/project.json +++ b/src/Microsoft.DotNet.Compiler.Common/project.json @@ -5,7 +5,7 @@ }, "dependencies": { "NETStandard.Library": "1.5.0-rc2-23911", - "System.CommandLine": "0.1.0-e160119-1", + "System.CommandLine": "0.1.0-e160323-1", "Microsoft.CodeAnalysis.CSharp": "1.2.0-beta1-20160202-02", "Microsoft.DotNet.ProjectModel": "1.0.0-*", "Microsoft.DotNet.Cli.Utils": "1.0.0-*", diff --git a/src/Microsoft.DotNet.ProjectModel.Loader/LoaderProjectContextExtensions.cs b/src/Microsoft.DotNet.ProjectModel.Loader/LoaderProjectContextExtensions.cs index 342b2aef1..b51841d79 100644 --- a/src/Microsoft.DotNet.ProjectModel.Loader/LoaderProjectContextExtensions.cs +++ b/src/Microsoft.DotNet.ProjectModel.Loader/LoaderProjectContextExtensions.cs @@ -22,7 +22,7 @@ namespace Microsoft.DotNet.ProjectModel.Loader foreach (var export in exporter.GetAllExports()) { // TODO: Handle resource assemblies - foreach (var asset in export.RuntimeAssemblies) + foreach (var asset in export.RuntimeAssemblyGroups.GetDefaultAssets()) { // REVIEW: Should we use the following? // AssemblyLoadContext.GetAssemblyName(asset.ResolvedPath); @@ -30,7 +30,7 @@ namespace Microsoft.DotNet.ProjectModel.Loader assemblies[assemblyName] = asset.ResolvedPath; } - foreach (var asset in export.NativeLibraries) + foreach (var asset in export.NativeLibraryGroups.GetDefaultAssets()) { dllImports[asset.Name] = asset.ResolvedPath; } diff --git a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryAssetGroup.cs b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryAssetGroup.cs new file mode 100644 index 000000000..fd1b9809f --- /dev/null +++ b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryAssetGroup.cs @@ -0,0 +1,29 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Linq; +using System.Collections.Generic; + +namespace Microsoft.DotNet.ProjectModel.Compilation +{ + public class LibraryAssetGroup + { + public LibraryAssetGroup(string runtime, params LibraryAsset[] assets) : this(runtime, (IEnumerable)assets) { } + public LibraryAssetGroup(params LibraryAsset[] assets) : this(string.Empty, (IEnumerable)assets) { } + public LibraryAssetGroup(IEnumerable assets) : this(string.Empty, assets) { } + + public LibraryAssetGroup(string runtime, + IEnumerable assets) + { + Runtime = runtime; + Assets = assets.ToArray(); + } + + public string Runtime { get; } + + /// + /// Gets a list of assets provided in this runtime group + /// + public IReadOnlyList Assets { get; } + } +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExport.cs b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExport.cs index 8d883495f..4e68c549b 100644 --- a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExport.cs +++ b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExport.cs @@ -15,9 +15,9 @@ namespace Microsoft.DotNet.ProjectModel.Compilation public LibraryDescription Library { get; } /// - /// Gets a list of fully-qualified paths to MSIL binaries required to run + /// Gets a list of MSIL binaries required to run /// - public IEnumerable RuntimeAssemblies { get; } + public IEnumerable RuntimeAssemblyGroups { get; } /// /// Non assembly runtime assets. @@ -25,9 +25,9 @@ namespace Microsoft.DotNet.ProjectModel.Compilation public IEnumerable RuntimeAssets { get; } /// - /// Gets a list of fully-qualified paths to native binaries required to run + /// Gets a list of native binaries required to run /// - public IEnumerable NativeLibraries { get; } + public IEnumerable NativeLibraryGroups { get; } /// /// Gets a list of fully-qualified paths to MSIL metadata references @@ -49,11 +49,6 @@ namespace Microsoft.DotNet.ProjectModel.Compilation /// public IEnumerable AnalyzerReferences { get; } - /// - /// Get a list of runtime targets provided by this export. - /// - public IEnumerable RuntimeTargets { get; } - /// /// Get a list of resource assemblies provided by this export. /// @@ -62,23 +57,21 @@ namespace Microsoft.DotNet.ProjectModel.Compilation public LibraryExport(LibraryDescription library, IEnumerable compileAssemblies, IEnumerable sourceReferences, - IEnumerable runtimeAssemblies, + IEnumerable runtimeAssemblyGroups, IEnumerable runtimeAssets, - IEnumerable nativeLibraries, + IEnumerable nativeLibraryGroups, IEnumerable embeddedResources, IEnumerable analyzers, - IEnumerable runtimeTargets, IEnumerable resourceAssemblies) { Library = library; CompilationAssemblies = compileAssemblies; SourceReferences = sourceReferences; - RuntimeAssemblies = runtimeAssemblies; + RuntimeAssemblyGroups = runtimeAssemblyGroups; RuntimeAssets = runtimeAssets; - NativeLibraries = nativeLibraries; + NativeLibraryGroups = nativeLibraryGroups; EmbeddedResources = embeddedResources; AnalyzerReferences = analyzers; - RuntimeTargets = runtimeTargets; ResourceAssemblies = resourceAssemblies; } diff --git a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExportBuilder.cs b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExportBuilder.cs index 5b764781b..be8980f6f 100644 --- a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExportBuilder.cs +++ b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExportBuilder.cs @@ -8,7 +8,7 @@ namespace Microsoft.DotNet.ProjectModel.Compilation { public class LibraryExportBuilder { - private IList _runtimeAssemblies; + private IList _runtimeAssemblyGroups; private IList _runtimeAssets; @@ -18,19 +18,17 @@ namespace Microsoft.DotNet.ProjectModel.Compilation private IList _sourceReferences; - private IList _nativeLibraries; + private IList _nativeLibraryGroups; private IList _embeddedResources; private IList _analyzerReferences; - private IList _runtimeTargets; - private IList _resourceAssemblies; public LibraryDescription Library { get; set; } - public IEnumerable RuntimeAssemblies => _runtimeAssemblies; + public IEnumerable RuntimeAssemblyGroups => _runtimeAssemblyGroups; public IEnumerable RuntimeAssets => _runtimeAssets; @@ -40,14 +38,12 @@ namespace Microsoft.DotNet.ProjectModel.Compilation public IEnumerable SourceReferences => _sourceReferences; - public IEnumerable NativeLibraries => _nativeLibraries; + public IEnumerable NativeLibraryGroups => _nativeLibraryGroups; public IEnumerable EmbeddedResources => _embeddedResources; public IEnumerable AnalyzerReferences => _analyzerReferences; - public IEnumerable RuntimeTargets => _runtimeTargets; - public IEnumerable ResourceAssemblies => _resourceAssemblies; public static LibraryExportBuilder Create(LibraryDescription library = null) @@ -65,12 +61,11 @@ namespace Microsoft.DotNet.ProjectModel.Compilation Library, CompilationAssemblies ?? EmptyArray.Value, SourceReferences ?? EmptyArray.Value, - RuntimeAssemblies ?? EmptyArray.Value, + RuntimeAssemblyGroups ?? EmptyArray.Value, RuntimeAssets ?? EmptyArray.Value, - NativeLibraries ?? EmptyArray.Value, + NativeLibraryGroups ?? EmptyArray.Value, EmbeddedResources ?? EmptyArray.Value, AnalyzerReferences ?? EmptyArray.Value, - RuntimeTargets ?? EmptyArray.Value, ResourceAssemblies ?? EmptyArray.Value); } @@ -80,9 +75,9 @@ namespace Microsoft.DotNet.ProjectModel.Compilation return this; } - public LibraryExportBuilder WithRuntimeAssemblies(IEnumerable assets) + public LibraryExportBuilder WithRuntimeAssemblyGroups(IEnumerable assets) { - Replace(ref _runtimeAssemblies, assets); + Replace(ref _runtimeAssemblyGroups, assets); return this; } @@ -104,9 +99,9 @@ namespace Microsoft.DotNet.ProjectModel.Compilation return this; } - public LibraryExportBuilder WithNativeLibraries(IEnumerable assets) + public LibraryExportBuilder WithNativeLibraryGroups(IEnumerable assets) { - Replace(ref _nativeLibraries, assets); + Replace(ref _nativeLibraryGroups, assets); return this; } @@ -122,21 +117,15 @@ namespace Microsoft.DotNet.ProjectModel.Compilation return this; } - public LibraryExportBuilder WithRuntimeTargets(IEnumerable targets) - { - Replace(ref _runtimeTargets, targets); - return this; - } - public LibraryExportBuilder WithResourceAssemblies(IEnumerable assemblies) { Replace(ref _resourceAssemblies, assemblies); return this; } - public LibraryExportBuilder AddRuntimeAssembly(LibraryAsset asset) + public LibraryExportBuilder AddRuntimeAssemblyGroup(LibraryAssetGroup asset) { - Add(ref _runtimeAssemblies, asset); + Add(ref _runtimeAssemblyGroups, asset); return this; } @@ -158,9 +147,9 @@ namespace Microsoft.DotNet.ProjectModel.Compilation return this; } - public LibraryExportBuilder AddNativeLibrary(LibraryAsset asset) + public LibraryExportBuilder AddNativeLibraryGroup(LibraryAssetGroup asset) { - Add(ref _compilationAssets, asset); + Add(ref _nativeLibraryGroups, asset); return this; } @@ -176,12 +165,6 @@ namespace Microsoft.DotNet.ProjectModel.Compilation return this; } - public LibraryExportBuilder AddRuntimeTarget(LibraryRuntimeTarget target) - { - Add(ref _runtimeTargets, target); - return this; - } - public LibraryExportBuilder AddResourceAssembly(LibraryResourceAssembly assembly) { Add(ref _resourceAssemblies, assembly); diff --git a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs index ba21b79e9..95b91cf7d 100644 --- a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs +++ b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs @@ -117,13 +117,12 @@ namespace Microsoft.DotNet.ProjectModel.Compilation yield return LibraryExportBuilder.Create(library) .WithCompilationAssemblies(compilationAssemblies) .WithSourceReferences(sourceReferences) - .WithRuntimeAssemblies(libraryExport.RuntimeAssemblies) + .WithRuntimeAssemblyGroups(libraryExport.RuntimeAssemblyGroups) .WithRuntimeAssets(libraryExport.RuntimeAssets) - .WithNativeLibraries(libraryExport.NativeLibraries) + .WithNativeLibraryGroups(libraryExport.NativeLibraryGroups) .WithEmbedddedResources(libraryExport.EmbeddedResources) .WithAnalyzerReference(analyzerReferences) .WithResourceAssemblies(libraryExport.ResourceAssemblies) - .WithRuntimeTargets(libraryExport.RuntimeTargets) .Build(); } } @@ -158,8 +157,8 @@ namespace Microsoft.DotNet.ProjectModel.Compilation private LibraryExport ExportPackage(PackageDescription package) { var builder = LibraryExportBuilder.Create(package); - builder.WithNativeLibraries(PopulateAssets(package, package.NativeLibraries)); - builder.WithRuntimeAssemblies(PopulateAssets(package, package.RuntimeAssemblies)); + builder.AddNativeLibraryGroup(new LibraryAssetGroup(PopulateAssets(package, package.NativeLibraries))); + builder.AddRuntimeAssemblyGroup(new LibraryAssetGroup(PopulateAssets(package, package.RuntimeAssemblies))); builder.WithCompilationAssemblies(PopulateAssets(package, package.CompileTimeAssemblies)); builder.WithSourceReferences(GetSharedSources(package)); builder.WithAnalyzerReference(GetAnalyzerReferences(package)); @@ -220,7 +219,15 @@ namespace Microsoft.DotNet.ProjectModel.Compilation } } - builder.AddRuntimeTarget(new LibraryRuntimeTarget(targetGroup.Key, runtime, native)); + if (runtime.Any()) + { + builder.AddRuntimeAssemblyGroup(new LibraryAssetGroup(targetGroup.Key, runtime)); + } + + if (native.Any()) + { + builder.AddNativeLibraryGroup(new LibraryAssetGroup(targetGroup.Key, native)); + } } } @@ -243,7 +250,7 @@ namespace Microsoft.DotNet.ProjectModel.Compilation assemblyPath); builder.AddCompilationAssembly(compileAsset); - builder.AddRuntimeAssembly(compileAsset); + builder.AddRuntimeAssemblyGroup(new LibraryAssetGroup(new[] { compileAsset })); if (File.Exists(pdbPath)) { builder.AddRuntimeAsset(new LibraryAsset(Path.GetFileName(pdbPath), Path.GetFileName(pdbPath), pdbPath)); @@ -266,12 +273,12 @@ namespace Microsoft.DotNet.ProjectModel.Compilation outputPaths.RuntimeFiles.BasePath, outputPaths.RuntimeFiles.Assembly); - builder.AddRuntimeAssembly(runtimeAssemblyAsset); + builder.AddRuntimeAssemblyGroup(new LibraryAssetGroup(new[] { runtimeAssemblyAsset })); builder.WithRuntimeAssets(CollectAssets(outputPaths.RuntimeFiles)); } else { - builder.AddRuntimeAssembly(compilationAssemblyAsset); + builder.AddRuntimeAssemblyGroup(new LibraryAssetGroup(new[] { compilationAssemblyAsset })); builder.WithRuntimeAssets(CollectAssets(outputPaths.CompilationFiles)); } } @@ -324,7 +331,7 @@ namespace Microsoft.DotNet.ProjectModel.Compilation var builder = LibraryExportBuilder.Create(library); if (!string.IsNullOrEmpty(library.Path)) { - builder.WithCompilationAssemblies(new [] + builder.WithCompilationAssemblies(new[] { new LibraryAsset(library.Identity.Name, null, library.Path) }); diff --git a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryRuntimeTarget.cs b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryRuntimeTarget.cs deleted file mode 100644 index 9bf303411..000000000 --- a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryRuntimeTarget.cs +++ /dev/null @@ -1,32 +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.Linq; -using System.Collections.Generic; - -namespace Microsoft.DotNet.ProjectModel.Compilation -{ - public class LibraryRuntimeTarget - { - public LibraryRuntimeTarget(string runtime, - IEnumerable runtimeAssemblies, - IEnumerable nativeLibraries) - { - Runtime = runtime; - RuntimeAssemblies = runtimeAssemblies.ToArray(); - NativeLibraries = nativeLibraries.ToArray(); - } - - public string Runtime { get; } - - /// - /// Gets a list of fully-qualified paths to MSIL binaries required to run - /// - public IReadOnlyList RuntimeAssemblies { get; } - - /// - /// Gets a list of fully-qualified paths to native binaries required to run - /// - public IReadOnlyList NativeLibraries { get; } - } -} \ No newline at end of file diff --git a/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs b/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs index d36ac6f82..60eb4bc77 100644 --- a/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs +++ b/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -90,16 +91,10 @@ namespace Microsoft.Extensions.DependencyModel var serviceable = (export.Library as PackageDescription)?.Library.IsServiceable ?? false; var libraryDependencies = new HashSet(); - var libraryAssets = runtime ? export.RuntimeAssemblies : export.CompilationAssemblies; - foreach (var libraryDependency in export.Library.Dependencies) { // skip build time dependencies - if (!libraryDependency.Type.HasFlag( - LibraryDependencyTypeFlag.MainReference | - LibraryDependencyTypeFlag.MainExport | - LibraryDependencyTypeFlag.RuntimeComponent | - LibraryDependencyTypeFlag.BecomesNupkgDependency)) + if (libraryDependency.Type.Equals(LibraryDependencyType.Build)) { continue; } @@ -111,16 +106,6 @@ namespace Microsoft.Extensions.DependencyModel } } - IEnumerable assemblies; - if (type == LibraryType.ReferenceAssembly) - { - assemblies = ResolveReferenceAssembliesPath(libraryAssets); - } - else - { - assemblies = libraryAssets.Select(libraryAsset => libraryAsset.RelativePath); - } - if (runtime) { return new RuntimeLibrary( @@ -128,16 +113,25 @@ namespace Microsoft.Extensions.DependencyModel export.Library.Identity.Name, export.Library.Identity.Version.ToString(), export.Library.Hash, - assemblies.Select(RuntimeAssembly.Create), - export.NativeLibraries.Select(l => l.RelativePath), + export.RuntimeAssemblyGroups.Select(CreateRuntimeAssetGroup).ToArray(), + export.NativeLibraryGroups.Select(CreateRuntimeAssetGroup).ToArray(), export.ResourceAssemblies.Select(CreateResourceAssembly), - export.RuntimeTargets.Select(CreateRuntimeTarget), libraryDependencies, serviceable ); } else { + IEnumerable assemblies; + if (type == LibraryType.ReferenceAssembly) + { + assemblies = ResolveReferenceAssembliesPath(export.CompilationAssemblies); + } + else + { + assemblies = export.CompilationAssemblies.Select(libraryAsset => libraryAsset.RelativePath); + } + return new CompilationLibrary( type.ToString().ToLowerInvariant(), export.Library.Identity.Name, @@ -145,11 +139,17 @@ namespace Microsoft.Extensions.DependencyModel export.Library.Hash, assemblies, libraryDependencies, - serviceable - ); + serviceable); } } + private RuntimeAssetGroup CreateRuntimeAssetGroup(LibraryAssetGroup libraryAssetGroup) + { + return new RuntimeAssetGroup( + libraryAssetGroup.Runtime, + libraryAssetGroup.Assets.Select(a => a.RelativePath)); + } + private ResourceAssembly CreateResourceAssembly(LibraryResourceAssembly resourceAssembly) { return new ResourceAssembly( @@ -158,15 +158,6 @@ namespace Microsoft.Extensions.DependencyModel ); } - private RuntimeTarget CreateRuntimeTarget(LibraryRuntimeTarget runtimeTarget) - { - return new RuntimeTarget( - runtime: runtimeTarget.Runtime, - assemblies: runtimeTarget.RuntimeAssemblies.Select(a => RuntimeAssembly.Create(a.RelativePath)), - nativeLibraries: runtimeTarget.NativeLibraries.Select(l => l.RelativePath) - ); - } - private IEnumerable ResolveReferenceAssembliesPath(IEnumerable libraryAssets) { var referenceAssembliesPath = diff --git a/src/Microsoft.DotNet.ProjectModel/ErrorCodes.DotNet.cs b/src/Microsoft.DotNet.ProjectModel/ErrorCodes.DotNet.cs index 566c4e2b8..095bbf9b2 100644 --- a/src/Microsoft.DotNet.ProjectModel/ErrorCodes.DotNet.cs +++ b/src/Microsoft.DotNet.ProjectModel/ErrorCodes.DotNet.cs @@ -10,5 +10,8 @@ namespace Microsoft.DotNet.ProjectModel // Reference assemblies location not specified public static readonly string DOTNET1012 = nameof(DOTNET1012); + + // Multiple libraries marked as "platform" + public static readonly string DOTNET1013 = nameof(DOTNET1013); } } diff --git a/src/Microsoft.DotNet.ProjectModel/Graph/LibraryDependencyType.cs b/src/Microsoft.DotNet.ProjectModel/Graph/LibraryDependencyType.cs index 912cd5a51..e2ea7c2d7 100644 --- a/src/Microsoft.DotNet.ProjectModel/Graph/LibraryDependencyType.cs +++ b/src/Microsoft.DotNet.ProjectModel/Graph/LibraryDependencyType.cs @@ -5,45 +5,28 @@ using System; namespace Microsoft.DotNet.ProjectModel.Graph { - public struct LibraryDependencyType + public struct LibraryDependencyType : IEquatable, IEquatable { - public static LibraryDependencyType Default = LibraryDependencyType.Parse("default"); + public static LibraryDependencyType Empty = new LibraryDependencyType(); + public static LibraryDependencyType Default = new LibraryDependencyType("default"); + public static LibraryDependencyType Build = new LibraryDependencyType("build"); + public static LibraryDependencyType Platform = new LibraryDependencyType("platform"); - public static LibraryDependencyType Build = LibraryDependencyType.Parse("build"); + public string Value { get; } - public LibraryDependencyTypeFlag Flags { get; private set; } - - private LibraryDependencyType(LibraryDependencyTypeFlag flags) + private LibraryDependencyType(string value) { - Flags = flags; + Value = value; } - public static LibraryDependencyType Parse(string keyword) - { - if (string.Equals(keyword, "default", StringComparison.OrdinalIgnoreCase) || - string.IsNullOrEmpty(keyword)) // Need the default value of the struct to behave like "default" - { - return new LibraryDependencyType( - LibraryDependencyTypeFlag.MainReference | - LibraryDependencyTypeFlag.MainSource | - LibraryDependencyTypeFlag.MainExport | - LibraryDependencyTypeFlag.RuntimeComponent | - LibraryDependencyTypeFlag.BecomesNupkgDependency); - } + public static LibraryDependencyType Parse(string value) => new LibraryDependencyType(value.ToLowerInvariant()); - if (string.Equals(keyword, "build", StringComparison.OrdinalIgnoreCase)) - { - return new LibraryDependencyType( - LibraryDependencyTypeFlag.MainSource | - LibraryDependencyTypeFlag.PreprocessComponent); - } + public override int GetHashCode() => Value.GetHashCode(); - throw new InvalidOperationException(string.Format("unknown keyword {0}", keyword)); - } + public override bool Equals(object obj) => obj is LibraryDependencyType && Equals((LibraryDependencyType)obj); - public bool HasFlag(LibraryDependencyTypeFlag flag) - { - return (Flags & flag) != 0; - } + public bool Equals(string other) => string.Equals(Value, other, StringComparison.Ordinal); + + public bool Equals(LibraryDependencyType other) => string.Equals(Value, other.Value, StringComparison.Ordinal); } } diff --git a/src/Microsoft.DotNet.ProjectModel/Graph/LibraryDependencyTypeFlag.cs b/src/Microsoft.DotNet.ProjectModel/Graph/LibraryDependencyTypeFlag.cs deleted file mode 100644 index 15aaa95cd..000000000 --- a/src/Microsoft.DotNet.ProjectModel/Graph/LibraryDependencyTypeFlag.cs +++ /dev/null @@ -1,21 +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; - -namespace Microsoft.DotNet.ProjectModel.Graph -{ - [Flags] - public enum LibraryDependencyTypeFlag - { - None = 0, - MainReference = 1 << 0, - MainSource = 1 << 1, - MainExport = 1 << 2, - PreprocessReference = 1 << 3, - RuntimeComponent = 1 << 4, - DevComponent = 1 << 5, - PreprocessComponent = 1 << 6, - BecomesNupkgDependency = 1 << 7, - } -} diff --git a/src/Microsoft.DotNet.ProjectModel/Graph/LibraryRange.cs b/src/Microsoft.DotNet.ProjectModel/Graph/LibraryRange.cs index 870cde381..0b49938c7 100644 --- a/src/Microsoft.DotNet.ProjectModel/Graph/LibraryRange.cs +++ b/src/Microsoft.DotNet.ProjectModel/Graph/LibraryRange.cs @@ -145,10 +145,5 @@ namespace Microsoft.DotNet.ProjectModel.Graph return sb.ToString(); } - - public bool HasFlag(LibraryDependencyTypeFlag flag) - { - return Type.HasFlag(flag); - } } } \ No newline at end of file diff --git a/src/Microsoft.DotNet.ProjectModel/Resolution/LibraryManager.cs b/src/Microsoft.DotNet.ProjectModel/Resolution/LibraryManager.cs index 1a776e52a..98fdc5038 100644 --- a/src/Microsoft.DotNet.ProjectModel/Resolution/LibraryManager.cs +++ b/src/Microsoft.DotNet.ProjectModel/Resolution/LibraryManager.cs @@ -41,6 +41,7 @@ namespace Microsoft.DotNet.ProjectModel.Resolution var dependencies = new Dictionary>(); var topLevel = new List(); + var platformLibraries = new List(); foreach (var library in GetLibraries()) { if (!library.Resolved) @@ -67,6 +68,11 @@ namespace Microsoft.DotNet.ProjectModel.Resolution } else { + var isPlatform = library.RequestedRanges.Any(r => r.Type.Equals(LibraryDependencyType.Platform)); + if (isPlatform) + { + platformLibraries.Add(library); + } // Store dependency -> library for later // J.N -> [(R1, P1), (R2, P2)] foreach (var dependency in library.Dependencies) @@ -128,6 +134,20 @@ namespace Microsoft.DotNet.ProjectModel.Resolution } } + if (platformLibraries.Count > 1) + { + foreach (var platformLibrary in platformLibraries) + { + AddDiagnostics( + messages, + platformLibrary, + "The following dependencies are marked with type 'platform', however only one dependency can have this type: " + + string.Join(", ", platformLibraries.Select(l => l.Identity.Name).ToArray()), + DiagnosticMessageSeverity.Error, + ErrorCodes.DOTNET1013); + } + } + // Version conflicts foreach (var libraryItem in topLevel) { @@ -186,10 +206,10 @@ namespace Microsoft.DotNet.ProjectModel.Resolution return range.Name + " " + VersionUtility.RenderVersion(range.VersionRange); } - private void AddDiagnostics(List messages, - LibraryDescription library, - string message, - DiagnosticMessageSeverity severity, + private void AddDiagnostics(List messages, + LibraryDescription library, + string message, + DiagnosticMessageSeverity severity, string errorCode) { // A (in project.json) -> B (unresolved) (not in project.json) diff --git a/src/Microsoft.DotNet.ProjectModel/Utilities/CollectionExtensions.cs b/src/Microsoft.DotNet.ProjectModel/Utilities/CollectionExtensions.cs new file mode 100644 index 000000000..6bb65ef5f --- /dev/null +++ b/src/Microsoft.DotNet.ProjectModel/Utilities/CollectionExtensions.cs @@ -0,0 +1,40 @@ +using Microsoft.DotNet.ProjectModel.Compilation; +using System.Linq; + +namespace System.Collections.Generic +{ + public static class CollectionExtensions + { + public static LibraryAssetGroup GetDefaultGroup(this IEnumerable self) => GetGroup(self, string.Empty); + public static LibraryAssetGroup GetRuntimeGroup(this IEnumerable self, string runtime) + { + if(string.IsNullOrEmpty(runtime)) + { + throw new ArgumentNullException(nameof(runtime)); + } + return GetGroup(self, runtime); + } + + private static LibraryAssetGroup GetGroup(IEnumerable groups, string runtime) + { + return groups.FirstOrDefault(g => g.Runtime == runtime); + } + + public static IEnumerable GetDefaultAssets(this IEnumerable self) => GetAssets(self, string.Empty); + public static IEnumerable GetRuntimeAssets(this IEnumerable self, string runtime) + { + if(string.IsNullOrEmpty(runtime)) + { + throw new ArgumentNullException(nameof(runtime)); + } + return GetAssets(self, runtime); + } + + private static IEnumerable GetAssets(IEnumerable self, string runtime) + { + return self + .Where(a => string.Equals(a.Runtime, runtime, StringComparison.Ordinal)) + .SelectMany(a => a.Assets); + } + } +} diff --git a/src/Microsoft.DotNet.ProjectModel/project.json b/src/Microsoft.DotNet.ProjectModel/project.json index 46cd0f97c..0f5a5702f 100644 --- a/src/Microsoft.DotNet.ProjectModel/project.json +++ b/src/Microsoft.DotNet.ProjectModel/project.json @@ -5,8 +5,8 @@ }, "description": "Types to model a .NET Project", "dependencies": { - "System.Reflection.Metadata": "1.2.0-rc2-23911", - "NuGet.Packaging": "3.4.0-rtm-0763", + "System.Reflection.Metadata": "1.2.0-rc2-23904", + "NuGet.Packaging": "3.5.0-beta-1034", "Microsoft.Extensions.FileSystemGlobbing": "1.0.0-rc2-15996", "Microsoft.Extensions.JsonParser.Sources": { "type": "build", @@ -37,8 +37,9 @@ "dependencies": { "NETStandard.Library": "1.5.0-rc2-23911", "System.Dynamic.Runtime": "4.0.11-rc2-23911", + "System.Threading.Thread": "4.0.0-rc2-23911", "System.Runtime.Loader": "4.0.0-rc2-23911", - "System.Security.Cryptography.Algorithms": "4.0.0-rc2-23911", + "System.Security.Cryptography.Algorithms": "4.1.0-rc2-23911", "Microsoft.CSharp": "4.0.1-rc2-23911", "System.Xml.XDocument": "4.0.11-rc2-23911" } diff --git a/src/Microsoft.Extensions.DependencyModel/CollectionExtensions.cs b/src/Microsoft.Extensions.DependencyModel/CollectionExtensions.cs new file mode 100644 index 000000000..6e3f94356 --- /dev/null +++ b/src/Microsoft.Extensions.DependencyModel/CollectionExtensions.cs @@ -0,0 +1,40 @@ +using Microsoft.Extensions.DependencyModel; +using System.Linq; + +namespace System.Collections.Generic +{ + public static class CollectionExtensions + { + public static RuntimeAssetGroup GetDefaultGroup(this IEnumerable self) => GetGroup(self, string.Empty); + public static RuntimeAssetGroup GetRuntimeGroup(this IEnumerable self, string runtime) + { + if(string.IsNullOrEmpty(runtime)) + { + throw new ArgumentNullException(nameof(runtime)); + } + return GetGroup(self, runtime); + } + + private static RuntimeAssetGroup GetGroup(IEnumerable groups, string runtime) + { + return groups.FirstOrDefault(g => g.Runtime == runtime); + } + + public static IEnumerable GetDefaultAssets(this IEnumerable self) => GetAssets(self, string.Empty); + public static IEnumerable GetRuntimeAssets(this IEnumerable self, string runtime) + { + if(string.IsNullOrEmpty(runtime)) + { + throw new ArgumentNullException(nameof(runtime)); + } + return GetAssets(self, runtime); + } + + private static IEnumerable GetAssets(IEnumerable groups, string runtime) + { + return groups + .Where(a => string.Equals(a.Runtime, runtime, StringComparison.Ordinal)) + .SelectMany(a => a.AssetPaths); + } + } +} diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs index d955b02e1..bd4a200f4 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs @@ -6,6 +6,7 @@ using System.IO; using System.Reflection; using System.Collections.Generic; using System.Linq; +using Microsoft.Extensions.PlatformAbstractions; namespace Microsoft.Extensions.DependencyModel { @@ -95,7 +96,7 @@ namespace Microsoft.Extensions.DependencyModel return DependencyContextLoader.Default.Load(assembly); } - private class LibraryMergeEqualityComparer: IEqualityComparer where T:Library + private class LibraryMergeEqualityComparer : IEqualityComparer where T : Library { public bool Equals(T x, T y) { diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextExtensions.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextExtensions.cs new file mode 100644 index 000000000..db68b3e0d --- /dev/null +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextExtensions.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace Microsoft.Extensions.DependencyModel +{ + public static class DependencyContextExtensions + { + private const string NativeImageSufix = ".ni"; + + public static IEnumerable GetDefaultNativeAssets(this DependencyContext self) + { + return ResolveAssets(self, string.Empty, l => l.NativeLibraryGroups); + } + + public static IEnumerable GetRuntimeNativeAssets(this DependencyContext self, string runtimeIdentifier) + { + return ResolveAssets(self, runtimeIdentifier, l => l.NativeLibraryGroups); + } + + public static IEnumerable GetDefaultAssemblyNames(this DependencyContext self) + { + return ResolveAssets(self, string.Empty, l => l.RuntimeAssemblyGroups).Select(GetAssemblyName); + } + + public static IEnumerable GetRuntimeAssemblyNames(this DependencyContext self, string runtimeIdentifier) + { + return ResolveAssets(self, runtimeIdentifier, l => l.RuntimeAssemblyGroups).Select(GetAssemblyName); + } + + private static string GetAssemblyName(string assetPath) + { + var name = Path.GetFileNameWithoutExtension(assetPath); + if (name == null) + { + throw new ArgumentException($"Provided path has empty file name '{assetPath}'", nameof(assetPath)); + } + + if (name.EndsWith(NativeImageSufix)) + { + name = name.Substring(0, name.Length - NativeImageSufix.Length); + } + + return name; + } + + private static IEnumerable ResolveAssets(DependencyContext context, string runtimeIdentifier, Func> groupSelector) + { + var fallbacks = context.RuntimeGraph.FirstOrDefault(f => f.Runtime == runtimeIdentifier); + var rids = Enumerable.Concat(new[] { runtimeIdentifier }, fallbacks?.Fallbacks ?? Enumerable.Empty()); + return context.RuntimeLibraries.SelectMany(l => SelectAssets(rids, groupSelector(l))); + } + + private static IEnumerable SelectAssets(IEnumerable rids, IEnumerable groups) + { + foreach (var rid in rids) + { + var group = groups.FirstOrDefault(g => g.Runtime == rid); + if (group != null) + { + return group.AssetPaths; + } + } + + // Return the RID-agnostic group + return groups.GetDefaultAssets(); + } + + } +} diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs index ceb2f5c2d..110fcd459 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs @@ -10,7 +10,7 @@ using Newtonsoft.Json.Linq; namespace Microsoft.Extensions.DependencyModel { - public class DependencyContextJsonReader: IDependencyContextReader + public class DependencyContextJsonReader : IDependencyContextReader { public DependencyContext Read(Stream stream) { @@ -38,8 +38,8 @@ namespace Microsoft.Extensions.DependencyModel var runtimeTargetName = root[DependencyContextStrings.RuntimeTargetPropertyName]?.Value(); - var libraryStubs = ReadLibraryStubs((JObject) root[DependencyContextStrings.LibrariesPropertyName]); - var targetsObject = (JObject) root[DependencyContextStrings.TargetsPropertyName]; + var libraryStubs = ReadLibraryStubs((JObject)root[DependencyContextStrings.LibrariesPropertyName]); + var targetsObject = (JObject)root[DependencyContextStrings.TargetsPropertyName]; JObject runtimeTarget = null; JObject compileTarget = null; @@ -51,7 +51,7 @@ namespace Microsoft.Extensions.DependencyModel if (!string.IsNullOrEmpty(runtimeTargetName)) { - runtimeTarget = (JObject) targetsObject[runtimeTargetName]; + runtimeTarget = (JObject)targetsObject[runtimeTargetName]; if (runtimeTarget == null) { throw new FormatException($"Target with name {runtimeTargetName} not found"); @@ -168,39 +168,56 @@ namespace Microsoft.Extensions.DependencyModel var name = nameWithVersion.Substring(0, seperatorPosition); var version = nameWithVersion.Substring(seperatorPosition + 1); - var libraryObject = (JObject) property.Value; + var libraryObject = (JObject)property.Value; var dependencies = ReadDependencies(libraryObject); if (runtime) { - var runtimeTargets = new List(); var runtimeTargetsObject = (JObject)libraryObject[DependencyContextStrings.RuntimeTargetsPropertyName]; var entries = ReadRuntimeTargetEntries(runtimeTargetsObject).ToArray(); + var runtimeAssemblyGroups = new List(); + var nativeLibraryGroups = new List(); foreach (var ridGroup in entries.GroupBy(e => e.Rid)) { - var runtimeAssets = entries.Where(e => e.Type == DependencyContextStrings.RuntimeAssetType) - .Select(e => RuntimeAssembly.Create(e.Path)) - .ToArray(); - - var nativeAssets = entries.Where(e => e.Type == DependencyContextStrings.NativeAssetType) + var groupRuntimeAssemblies = entries.Where(e => e.Type == DependencyContextStrings.RuntimeAssetType) .Select(e => e.Path) .ToArray(); - runtimeTargets.Add(new RuntimeTarget( - ridGroup.Key, - runtimeAssets, - nativeAssets - )); + if (groupRuntimeAssemblies.Any()) + { + runtimeAssemblyGroups.Add(new RuntimeAssetGroup( + ridGroup.Key, + groupRuntimeAssemblies.Where(a => Path.GetFileName(a) != "_._"))); + } + + var groupNativeLibraries = entries.Where(e => e.Type == DependencyContextStrings.NativeAssetType) + .Select(e => e.Path) + .ToArray(); + + if (groupNativeLibraries.Any()) + { + nativeLibraryGroups.Add(new RuntimeAssetGroup( + ridGroup.Key, + groupNativeLibraries.Where(a => Path.GetFileName(a) != "_._"))); + } } - var assemblies = ReadAssetList(libraryObject, DependencyContextStrings.RuntimeAssembliesKey) - .Select(RuntimeAssembly.Create) + var runtimeAssemblies = ReadAssetList(libraryObject, DependencyContextStrings.RuntimeAssembliesKey) .ToArray(); + if (runtimeAssemblies.Any()) + { + runtimeAssemblyGroups.Add(new RuntimeAssetGroup(string.Empty, runtimeAssemblies)); + } - var nativeLibraries = ReadAssetList(libraryObject, DependencyContextStrings.NativeLibrariesKey); + var nativeLibraries = ReadAssetList(libraryObject, DependencyContextStrings.NativeLibrariesKey) + .ToArray(); + if(nativeLibraries.Any()) + { + nativeLibraryGroups.Add(new RuntimeAssetGroup(string.Empty, nativeLibraries)); + } var resourceAssemblies = ReadResourceAssemblies((JObject)libraryObject[DependencyContextStrings.ResourceAssembliesPropertyName]); @@ -209,10 +226,9 @@ namespace Microsoft.Extensions.DependencyModel name: name, version: version, hash: stub.Hash, - assemblies: assemblies, - nativeLibraries: nativeLibraries, + runtimeAssemblyGroups: runtimeAssemblyGroups, + nativeLibraryGroups: nativeLibraryGroups, resourceAssemblies: resourceAssemblies, - subTargets: runtimeTargets.ToArray(), dependencies: dependencies, serviceable: stub.Serviceable); } @@ -258,11 +274,11 @@ namespace Microsoft.Extensions.DependencyModel private static string[] ReadAssetList(JObject libraryObject, string name) { - var assembliesObject = (JObject) libraryObject[name]; + var assembliesObject = (JObject)libraryObject[name]; if (assembliesObject == null) { - return new string[] {}; + return new string[] { }; } return assembliesObject.Properties().Select(property => property.Name).ToArray(); @@ -270,15 +286,15 @@ namespace Microsoft.Extensions.DependencyModel private static Dependency[] ReadDependencies(JObject libraryObject) { - var dependenciesObject = (JObject) libraryObject[DependencyContextStrings.DependenciesPropertyName]; + var dependenciesObject = (JObject)libraryObject[DependencyContextStrings.DependenciesPropertyName]; if (dependenciesObject == null) { - return new Dependency[]{ }; + return new Dependency[] { }; } return dependenciesObject.Properties() - .Select(property => new Dependency(property.Name, (string) property.Value)).ToArray(); + .Select(property => new Dependency(property.Name, (string)property.Value)).ToArray(); } private Dictionary ReadLibraryStubs(JObject librariesObject) @@ -288,7 +304,7 @@ namespace Microsoft.Extensions.DependencyModel { foreach (var libraryProperty in librariesObject) { - var value = (JObject) libraryProperty.Value; + var value = (JObject)libraryProperty.Value; var stub = new LibraryStub { Name = libraryProperty.Key, diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs index 1a6015359..81c5cc9a7 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs @@ -35,7 +35,7 @@ namespace Microsoft.Extensions.DependencyModel private JObject Write(DependencyContext context) { - var contextObject = new JObject( + var contextObject = new JObject( new JProperty(DependencyContextStrings.RuntimeTargetPropertyName, WriteRuntimeTargetInfo(context)), new JProperty(DependencyContextStrings.CompilationOptionsPropertName, WriteCompilationOptions(context.CompilationOptions)), new JProperty(DependencyContextStrings.TargetsPropertyName, WriteTargets(context)), @@ -50,7 +50,7 @@ namespace Microsoft.Extensions.DependencyModel private string WriteRuntimeTargetInfo(DependencyContext context) { - return context.IsPortable? + return context.IsPortable ? context.TargetFramework : context.TargetFramework + DependencyContextStrings.VersionSeperator + context.Runtime; } @@ -84,12 +84,12 @@ namespace Microsoft.Extensions.DependencyModel } private void AddPropertyIfNotNull(JObject o, string name, T value) - { + { if (value != null) { o.Add(new JProperty(name, value)); } - } + } private JObject WriteTargets(DependencyContext context) { @@ -159,14 +159,14 @@ namespace Microsoft.Extensions.DependencyModel ); } - private void AddRuntimeAssemblies(JObject libraryObject, IEnumerable runtimeAssemblies) + private void AddAssets(JObject libraryObject, string key, RuntimeAssetGroup group) { - if (!runtimeAssemblies.Any()) + if (group == null || !group.AssetPaths.Any()) { return; } - libraryObject.Add(new JProperty(DependencyContextStrings.RuntimeAssembliesKey, - WriteAssetList(runtimeAssemblies.Select(a => a.Path))) + libraryObject.Add(new JProperty(key, + WriteAssetList(group.AssetPaths)) ); } @@ -203,13 +203,11 @@ namespace Microsoft.Extensions.DependencyModel { var libraryObject = new JObject(); AddDependencies(libraryObject, runtimeLibrary.Dependencies); - AddRuntimeAssemblies(libraryObject, runtimeLibrary.Assemblies); - AddResourceAssemblies(libraryObject, runtimeLibrary.ResourceAssemblies); - if (runtimeLibrary.NativeLibraries.Any()) - { - libraryObject.Add(DependencyContextStrings.NativeLibrariesKey, WriteAssetList(runtimeLibrary.NativeLibraries)); - } + // Add runtime-agnostic assets + AddAssets(libraryObject, DependencyContextStrings.RuntimeAssembliesKey, runtimeLibrary.RuntimeAssemblyGroups.GetDefaultGroup()); + AddAssets(libraryObject, DependencyContextStrings.NativeLibrariesKey, runtimeLibrary.NativeLibraryGroups.GetDefaultGroup()); + AddResourceAssemblies(libraryObject, runtimeLibrary.ResourceAssemblies); return libraryObject; } @@ -232,17 +230,19 @@ namespace Microsoft.Extensions.DependencyModel var dependencies = new HashSet(); if (runtimeLibrary != null) { - - if (runtimeLibrary.RuntimeTargets.Any()) - { - libraryObject.Add(new JProperty( - DependencyContextStrings.RuntimeTargetsPropertyName, - new JObject(runtimeLibrary.RuntimeTargets.SelectMany(WriteRuntimeTarget))) - ); - } - AddRuntimeAssemblies(libraryObject, runtimeLibrary.Assemblies); + // Add runtime-agnostic assets + AddAssets(libraryObject, DependencyContextStrings.RuntimeAssembliesKey, runtimeLibrary.RuntimeAssemblyGroups.GetDefaultGroup()); + AddAssets(libraryObject, DependencyContextStrings.NativeLibrariesKey, runtimeLibrary.NativeLibraryGroups.GetDefaultGroup()); AddResourceAssemblies(libraryObject, runtimeLibrary.ResourceAssemblies); - libraryObject.Add(DependencyContextStrings.NativeLibrariesKey, WriteAssetList(runtimeLibrary.NativeLibraries)); + + // Add runtime-specific assets + var runtimeTargets = new JObject(); + AddRuntimeSpecificAssetGroups(runtimeTargets, DependencyContextStrings.RuntimeAssetType, runtimeLibrary.RuntimeAssemblyGroups); + AddRuntimeSpecificAssetGroups(runtimeTargets, DependencyContextStrings.NativeAssetType, runtimeLibrary.NativeLibraryGroups); + if (runtimeTargets.Count > 0) + { + libraryObject.Add(DependencyContextStrings.RuntimeTargetsPropertyName, runtimeTargets); + } dependencies.UnionWith(runtimeLibrary.Dependencies); } @@ -258,31 +258,39 @@ namespace Microsoft.Extensions.DependencyModel return libraryObject; } - private IEnumerable WriteRuntimeTarget(RuntimeTarget target) + private void AddRuntimeSpecificAssetGroups(JObject runtimeTargets, string assetType, IEnumerable assetGroups) { - var runtime = WriteRuntimeTargetAssemblies( - target.Assemblies.Select(a => a.Path), - target.Runtime, - DependencyContextStrings.RuntimeAssetType); - - var native = WriteRuntimeTargetAssemblies( - target.NativeLibraries, - target.Runtime, - DependencyContextStrings.NativeAssetType); - - return runtime.Concat(native); + foreach (var group in assetGroups.Where(g => !string.IsNullOrEmpty(g.Runtime))) + { + if (group.AssetPaths.Any()) + { + AddRuntimeSpecificAssets(runtimeTargets, group.AssetPaths, group.Runtime, assetType); + } + else + { + // Add a placeholder item + // We need to generate a pseudo-path because there could be multiple different asset groups with placeholders + // Only the last path segment matters, the rest is basically just a GUID. + var pseudoPathFolder = assetType == DependencyContextStrings.RuntimeAssetType ? + "lib" : + "native"; + runtimeTargets[$"runtime/{group.Runtime}/{pseudoPathFolder}/_._"] = new JObject( + new JProperty(DependencyContextStrings.RidPropertyName, group.Runtime), + new JProperty(DependencyContextStrings.AssetTypePropertyName, assetType)); + } + } } - private IEnumerable WriteRuntimeTargetAssemblies(IEnumerable assemblies, string runtime, string assetType) + private void AddRuntimeSpecificAssets(JObject target, IEnumerable assets, string runtime, string assetType) { - foreach (var assembly in assemblies) + foreach (var asset in assets) { - yield return new JProperty(NormalizePath(assembly), + target.Add(new JProperty(NormalizePath(asset), new JObject( new JProperty(DependencyContextStrings.RidPropertyName, runtime), new JProperty(DependencyContextStrings.AssetTypePropertyName, assetType) ) - ); + )); } } @@ -297,7 +305,7 @@ namespace Microsoft.Extensions.DependencyModel context.RuntimeLibraries.Cast().Concat(context.CompileLibraries) .GroupBy(library => library.Name + DependencyContextStrings.VersionSeperator + library.Version); - return new JObject(allLibraries.Select(libraries=> new JProperty(libraries.Key, WriteLibrary(libraries.First())))); + return new JObject(allLibraries.Select(libraries => new JProperty(libraries.Key, WriteLibrary(libraries.First())))); } private JObject WriteLibrary(Library library) diff --git a/src/Microsoft.Extensions.DependencyModel/RuntimeAssembly.cs b/src/Microsoft.Extensions.DependencyModel/RuntimeAssembly.cs index 196a36c17..4dfd497fb 100644 --- a/src/Microsoft.Extensions.DependencyModel/RuntimeAssembly.cs +++ b/src/Microsoft.Extensions.DependencyModel/RuntimeAssembly.cs @@ -2,8 +2,6 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; -using System.Diagnostics; -using System.IO; using System.Reflection; namespace Microsoft.Extensions.DependencyModel diff --git a/src/Microsoft.Extensions.DependencyModel/RuntimeAssetGroup.cs b/src/Microsoft.Extensions.DependencyModel/RuntimeAssetGroup.cs new file mode 100644 index 000000000..d9eee3eb6 --- /dev/null +++ b/src/Microsoft.Extensions.DependencyModel/RuntimeAssetGroup.cs @@ -0,0 +1,29 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Linq; +using System.Collections.Generic; + +namespace Microsoft.Extensions.DependencyModel +{ + public class RuntimeAssetGroup + { + public RuntimeAssetGroup(string runtime, params string[] assetPaths) : this(runtime, (IEnumerable)assetPaths) { } + + public RuntimeAssetGroup(string runtime, IEnumerable assetPaths) + { + Runtime = runtime; + AssetPaths = assetPaths.ToArray(); + } + + /// + /// The runtime ID associated with this group (may be empty if the group is runtime-agnostic) + /// + public string Runtime { get; } + + /// + /// Gets a list of assets provided in this runtime group + /// + public IReadOnlyList AssetPaths { get; } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.DependencyModel/RuntimeFallbacks.cs b/src/Microsoft.Extensions.DependencyModel/RuntimeFallbacks.cs index d5ff52403..626aa5b24 100644 --- a/src/Microsoft.Extensions.DependencyModel/RuntimeFallbacks.cs +++ b/src/Microsoft.Extensions.DependencyModel/RuntimeFallbacks.cs @@ -12,6 +12,7 @@ namespace Microsoft.Extensions.DependencyModel public string Runtime { get; set; } public IReadOnlyList Fallbacks { get; set; } + public RuntimeFallbacks(string runtime, params string[] fallbacks) : this(runtime, (IEnumerable)fallbacks) { } public RuntimeFallbacks(string runtime, IEnumerable fallbacks) { if (string.IsNullOrEmpty(runtime)) diff --git a/src/Microsoft.Extensions.DependencyModel/RuntimeLibrary.cs b/src/Microsoft.Extensions.DependencyModel/RuntimeLibrary.cs index cc7accd3e..8cf195dfe 100644 --- a/src/Microsoft.Extensions.DependencyModel/RuntimeLibrary.cs +++ b/src/Microsoft.Extensions.DependencyModel/RuntimeLibrary.cs @@ -14,42 +14,41 @@ namespace Microsoft.Extensions.DependencyModel string name, string version, string hash, - IEnumerable assemblies, - IEnumerable nativeLibraries, + IReadOnlyList runtimeAssemblyGroups, + IReadOnlyList nativeLibraryGroups, IEnumerable resourceAssemblies, - IEnumerable subTargets, IEnumerable dependencies, bool serviceable) : base(type, name, version, hash, dependencies, serviceable) { - if (assemblies == null) + if (runtimeAssemblyGroups == null) { - throw new ArgumentNullException(nameof(assemblies)); + throw new ArgumentNullException(nameof(runtimeAssemblyGroups)); } - if (nativeLibraries == null) + if (nativeLibraryGroups == null) { - throw new ArgumentNullException(nameof(nativeLibraries)); + throw new ArgumentNullException(nameof(nativeLibraryGroups)); } if (resourceAssemblies == null) { throw new ArgumentNullException(nameof(resourceAssemblies)); } - if (subTargets == null) - { - throw new ArgumentNullException(nameof(subTargets)); - } - Assemblies = assemblies.ToArray(); + RuntimeAssemblyGroups = runtimeAssemblyGroups; ResourceAssemblies = resourceAssemblies.ToArray(); - RuntimeTargets = subTargets.ToArray(); - NativeLibraries = nativeLibraries.ToArray(); + NativeLibraryGroups = nativeLibraryGroups; + + Assemblies = new RuntimeAssembly[0]; + NativeLibraries = new string[0]; } + // Temporary (legacy) properties: https://github.com/dotnet/cli/issues/1998 public IReadOnlyList Assemblies { get; } - public IReadOnlyList NativeLibraries { get; } - public IReadOnlyList ResourceAssemblies { get; } + public IReadOnlyList RuntimeAssemblyGroups { get; } - public IReadOnlyList RuntimeTargets { get; } + public IReadOnlyList NativeLibraryGroups { get; } + + public IReadOnlyList ResourceAssemblies { get; } } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.DependencyModel/RuntimeTarget.cs b/src/Microsoft.Extensions.DependencyModel/RuntimeTarget.cs deleted file mode 100644 index 709e1073d..000000000 --- a/src/Microsoft.Extensions.DependencyModel/RuntimeTarget.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Microsoft.Extensions.DependencyModel -{ - public class RuntimeTarget - { - public RuntimeTarget(string runtime, IEnumerable assemblies, IEnumerable nativeLibraries) - { - if (string.IsNullOrEmpty(runtime)) - { - throw new ArgumentException(nameof(runtime)); - } - if (assemblies == null) - { - throw new ArgumentNullException(nameof(assemblies)); - } - if (nativeLibraries == null) - { - throw new ArgumentNullException(nameof(nativeLibraries)); - } - Runtime = runtime; - Assemblies = assemblies.ToArray(); - NativeLibraries = nativeLibraries.ToArray(); - } - - public string Runtime { get; } - - public IReadOnlyList Assemblies { get; } - - public IReadOnlyList NativeLibraries { get; } - } -} \ No newline at end of file diff --git a/src/Microsoft.Extensions.DependencyModel/project.json b/src/Microsoft.Extensions.DependencyModel/project.json index 65fd21652..30fc3f304 100644 --- a/src/Microsoft.Extensions.DependencyModel/project.json +++ b/src/Microsoft.Extensions.DependencyModel/project.json @@ -27,8 +27,8 @@ "imports": "dnxcore50", "dependencies": { "System.IO.FileSystem": "4.0.1-rc2-23911", - "System.Linq": "4.0.1-rc2-23911", - "System.Runtime": "4.0.21-rc2-23911", + "System.Linq": "4.1.0-rc2-23911", + "System.Runtime": "4.1.0-rc2-23911", "System.Reflection": "4.1.0-rc2-23911", "System.Dynamic.Runtime": "4.0.11-rc2-23911" } diff --git a/src/dotnet/commands/dotnet-build/CompileContext.cs b/src/dotnet/commands/dotnet-build/CompileContext.cs index fecb6454c..c385e78dd 100644 --- a/src/dotnet/commands/dotnet-build/CompileContext.cs +++ b/src/dotnet/commands/dotnet-build/CompileContext.cs @@ -440,31 +440,6 @@ namespace Microsoft.DotNet.Tools.Build var executable = new Executable(runtimeContext, outputPaths, libraryExporter, _args.ConfigValue); executable.MakeCompilationOutputRunnable(); - - PatchMscorlibNextToCoreClr(runtimeContext, _args.ConfigValue); - } - - // Workaround: CoreCLR packaging doesn't include side by side mscorlib, so copy it at build - // time. See: https://github.com/dotnet/cli/issues/1374 - private static void PatchMscorlibNextToCoreClr(ProjectContext context, string config) - { - foreach (var exp in context.CreateExporter(config).GetAllExports()) - { - var coreclrLib = exp.NativeLibraries.FirstOrDefault(nLib => - string.Equals(Constants.LibCoreClrFileName, nLib.Name)); - if (string.IsNullOrEmpty(coreclrLib.ResolvedPath)) - { - continue; - } - var coreclrDir = Path.GetDirectoryName(coreclrLib.ResolvedPath); - if (File.Exists(Path.Combine(coreclrDir, "mscorlib.dll")) || - File.Exists(Path.Combine(coreclrDir, "mscorlib.ni.dll"))) - { - continue; - } - var mscorlibFile = exp.RuntimeAssemblies.FirstOrDefault(r => r.Name.Equals("mscorlib") || r.Name.Equals("mscorlib.ni")).ResolvedPath; - File.Copy(mscorlibFile, Path.Combine(coreclrDir, Path.GetFileName(mscorlibFile)), overwrite: true); - } } private static ISet Sort(Dictionary projects) diff --git a/src/dotnet/commands/dotnet-compile/NativeCompiler.cs b/src/dotnet/commands/dotnet-compile/NativeCompiler.cs index 70ce600c3..a9eb6abb4 100644 --- a/src/dotnet/commands/dotnet-compile/NativeCompiler.cs +++ b/src/dotnet/commands/dotnet-compile/NativeCompiler.cs @@ -30,7 +30,7 @@ namespace Microsoft.DotNet.Tools.Compiler // Runtime assemblies. // TODO: native assets/resources. var references = exports - .SelectMany(export => export.RuntimeAssemblies) + .SelectMany(export => export.RuntimeAssemblyGroups.GetDefaultAssets()) .Select(r => r.ResolvedPath) .ToList(); diff --git a/src/dotnet/commands/dotnet-new/CSharp_Console/project.json.template b/src/dotnet/commands/dotnet-new/CSharp_Console/project.json.template index 5f0805e14..be12f3038 100644 --- a/src/dotnet/commands/dotnet-new/CSharp_Console/project.json.template +++ b/src/dotnet/commands/dotnet-new/CSharp_Console/project.json.template @@ -4,7 +4,7 @@ "emitEntryPoint": true }, "dependencies": { - "Microsoft.NETCore.App": "1.0.0-rc2-23911" + "Microsoft.NETCore.App": { "type": "platform", "version": "1.0.0-rc2-23911" } }, "frameworks": { "netstandard1.5": { diff --git a/src/dotnet/commands/dotnet-new/FSharp_Console/project.json.template b/src/dotnet/commands/dotnet-new/FSharp_Console/project.json.template index 3311f8d93..0a26a0595 100644 --- a/src/dotnet/commands/dotnet-new/FSharp_Console/project.json.template +++ b/src/dotnet/commands/dotnet-new/FSharp_Console/project.json.template @@ -9,7 +9,7 @@ ], "dependencies": { "Microsoft.FSharp.Core.netcore": "1.0.0-alpha-160316", - "Microsoft.NETCore.App": "1.0.0-rc2-23911" + "Microsoft.NETCore.App": { "type": "platform", "version": "1.0.0-rc2-23911" } }, "frameworks": { "netstandard1.5": { diff --git a/src/dotnet/commands/dotnet-pack/NuGet/EmptyFrameworkFolderFile.cs b/src/dotnet/commands/dotnet-pack/NuGet/EmptyFrameworkFolderFile.cs index f183ff274..eeabe193b 100644 --- a/src/dotnet/commands/dotnet-pack/NuGet/EmptyFrameworkFolderFile.cs +++ b/src/dotnet/commands/dotnet-pack/NuGet/EmptyFrameworkFolderFile.cs @@ -17,7 +17,7 @@ namespace NuGet { if (directoryPathInPackage == null) { - throw new ArgumentNullException("directoryPathInPackage"); + throw new ArgumentNullException(nameof(directoryPathInPackage)); } TargetPath = System.IO.Path.Combine(directoryPathInPackage, Constants.PackageEmptyFileName); diff --git a/src/dotnet/commands/dotnet-pack/NuGet/PackageIdValidator.cs b/src/dotnet/commands/dotnet-pack/NuGet/PackageIdValidator.cs index 4fa2ca9d6..efc20acea 100644 --- a/src/dotnet/commands/dotnet-pack/NuGet/PackageIdValidator.cs +++ b/src/dotnet/commands/dotnet-pack/NuGet/PackageIdValidator.cs @@ -17,7 +17,7 @@ namespace NuGet { if (packageId == null) { - throw new ArgumentNullException("packageId"); + throw new ArgumentNullException(nameof(packageId)); } return _idRegex.IsMatch(packageId); } diff --git a/src/dotnet/commands/dotnet-pack/PackageGenerator.cs b/src/dotnet/commands/dotnet-pack/PackageGenerator.cs index 9e9a5ffbc..ed8377670 100644 --- a/src/dotnet/commands/dotnet-pack/PackageGenerator.cs +++ b/src/dotnet/commands/dotnet-pack/PackageGenerator.cs @@ -258,7 +258,7 @@ namespace Microsoft.DotNet.Tools.Compiler foreach (var dependency in project.Dependencies) { - if (!dependency.HasFlag(LibraryDependencyTypeFlag.BecomesNupkgDependency)) + if (dependency.Type.Equals(LibraryDependencyType.Build)) { continue; } diff --git a/src/dotnet/commands/dotnet-publish/PublishCommand.cs b/src/dotnet/commands/dotnet-publish/PublishCommand.cs index 10576af28..aaf29b4ee 100644 --- a/src/dotnet/commands/dotnet-publish/PublishCommand.cs +++ b/src/dotnet/commands/dotnet-publish/PublishCommand.cs @@ -152,20 +152,15 @@ namespace Microsoft.DotNet.Tools.Publish // Use a library exporter to collect publish assets var exporter = context.CreateExporter(configuration); + var isPortable = string.IsNullOrEmpty(context.RuntimeIdentifier); foreach (var export in exporter.GetAllExports()) { Reporter.Verbose.WriteLine($"Publishing {export.Library.Identity.ToString().Green().Bold()} ..."); - PublishFiles(export.RuntimeAssemblies, outputPath, nativeSubdirectories: false, preserveRelativePath: false); - PublishFiles(export.NativeLibraries, outputPath, nativeSubdirectories, preserveRelativePath: false); + PublishAssetGroups(export.RuntimeAssemblyGroups, outputPath, nativeSubdirectories: false, includeRuntimeGroups: isPortable); + PublishAssetGroups(export.NativeLibraryGroups, outputPath, nativeSubdirectories, includeRuntimeGroups: isPortable); export.RuntimeAssets.StructuredCopyTo(outputPath, outputPaths.IntermediateOutputDirectoryPath); - if (string.IsNullOrEmpty(context.RuntimeIdentifier)) - { - var assets = export.RuntimeTargets.SelectMany(t => Enumerable.Concat(t.NativeLibraries, t.RuntimeAssemblies)); - PublishFiles(assets, outputPath, nativeSubdirectories: false, preserveRelativePath: true); - } - if (options.PreserveCompilationContext.GetValueOrDefault()) { PublishRefs(export, outputPath); @@ -212,7 +207,7 @@ namespace Microsoft.DotNet.Tools.Publish } // Do not copy compilation assembly if it's in runtime assemblies - var runtimeAssemblies = new HashSet(export.RuntimeAssemblies); + var runtimeAssemblies = new HashSet(export.RuntimeAssemblyGroups.GetDefaultAssets()); foreach (var compilationAssembly in export.CompilationAssemblies) { if (!runtimeAssemblies.Contains(compilationAssembly)) @@ -259,23 +254,26 @@ namespace Microsoft.DotNet.Tools.Publish } } - private static void PublishFiles(IEnumerable files, string outputPath, bool nativeSubdirectories, bool preserveRelativePath) + private void PublishAssetGroups(IEnumerable groups, string outputPath, bool nativeSubdirectories, bool includeRuntimeGroups) { - foreach (var file in files) + foreach (var group in groups.Where(g => includeRuntimeGroups || string.IsNullOrEmpty(g.Runtime))) { - var destinationDirectory = DetermineFileDestinationDirectory(file, outputPath, nativeSubdirectories); - - if (preserveRelativePath) + foreach (var file in group.Assets) { - destinationDirectory = Path.Combine(destinationDirectory, Path.GetDirectoryName(file.RelativePath)); - } + var destinationDirectory = DetermineFileDestinationDirectory(file, outputPath, nativeSubdirectories); - if (!Directory.Exists(destinationDirectory)) - { - Directory.CreateDirectory(destinationDirectory); - } + if (!string.IsNullOrEmpty(group.Runtime)) + { + destinationDirectory = Path.Combine(destinationDirectory, Path.GetDirectoryName(file.RelativePath)); + } - File.Copy(file.ResolvedPath, Path.Combine(destinationDirectory, file.FileName), overwrite: true); + if (!Directory.Exists(destinationDirectory)) + { + Directory.CreateDirectory(destinationDirectory); + } + + File.Copy(file.ResolvedPath, Path.Combine(destinationDirectory, file.FileName), overwrite: true); + } } } diff --git a/src/dotnet/commands/dotnet-repl-csi/Program.cs b/src/dotnet/commands/dotnet-repl-csi/Program.cs index 6a5ed89d4..57bef2fda 100644 --- a/src/dotnet/commands/dotnet-repl-csi/Program.cs +++ b/src/dotnet/commands/dotnet-repl-csi/Program.cs @@ -86,9 +86,9 @@ namespace Microsoft.DotNet.Tools.Repl.Csi foreach (var projectDependency in projectDependencies) { - var runtimeAssemblies = projectDependency.RuntimeAssemblies; + var runtimeAssemblies = projectDependency.RuntimeAssemblyGroups; - foreach (var runtimeAssembly in runtimeAssemblies) + foreach (var runtimeAssembly in runtimeAssemblies.GetDefaultAssets()) { var runtimeAssemblyPath = runtimeAssembly.ResolvedPath; runtimeDependencies.Add(runtimeAssemblyPath); diff --git a/src/dotnet/project.json b/src/dotnet/project.json index a373f3d1e..2ef6e57e8 100644 --- a/src/dotnet/project.json +++ b/src/dotnet/project.json @@ -16,21 +16,26 @@ "commands/dotnet-new/FSharp_Console/project.json.template" ], "dependencies": { + "NuGet.Commands": { + "version": "3.5.0-beta-1034", + "exclude": "compile" + }, + "NuGet.CommandLine.XPlat": "3.5.0-beta-1034", + "Newtonsoft.Json": "7.0.1", "Microsoft.Net.Compilers.netcore": "1.3.0-beta1-20160225-02", - "Microsoft.FSharp.Compiler.netcore": "1.0.0-alpha-160316", + "Microsoft.FSharp.Compiler.netcore": "1.0.0-alpha-151218", "Microsoft.Net.CSharp.Interactive.netcore": "1.3.0-beta1-20160225-02", "Microsoft.CodeAnalysis.CSharp": "1.3.0-beta1-20160225-02", "Microsoft.DiaSymReader.Native": "1.3.3", - "NuGet.CommandLine.XPlat": "3.4.0-rtm-0763", - "System.CommandLine": "0.1.0-e160119-1", + "System.CommandLine": "0.1.0-e160323-1", "Microsoft.DotNet.ProjectModel": "1.0.0-*", "Microsoft.DotNet.Compiler.Common": "1.0.0-*", "Microsoft.DotNet.Cli.Utils": "1.0.0-*", "Microsoft.DotNet.ILCompiler.SDK": "1.0.6-prerelease-00003", "Microsoft.Extensions.Logging": "1.0.0-rc2-16040", "Microsoft.Extensions.Logging.Console": "1.0.0-rc2-16040", - "Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-16537", + "Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-20100", "Microsoft.Extensions.CommandLineUtils.Sources": { "type": "build", "version": "1.0.0-rc2-16453" @@ -57,7 +62,7 @@ "System.Threading.ThreadPool": "4.0.10-rc2-23911", "Microsoft.Win32.Registry": { "version": "4.0.0-rc2-23911", - "exclude": "Compile" + "exclude": "compile" }, "System.Net.NameResolution": "4.0.0-rc2-23911" }, @@ -69,5 +74,5 @@ ] } }, - "scripts": {} + "scripts": { } } diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/project.json b/test/Microsoft.DotNet.Cli.Utils.Tests/project.json index 7be15c9ff..e89669933 100644 --- a/test/Microsoft.DotNet.Cli.Utils.Tests/project.json +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/project.json @@ -5,11 +5,11 @@ }, "dependencies": { "NETStandard.Library": "1.5.0-rc2-23911", - "NuGet.Versioning": "3.4.0-rtm-0763", - "NuGet.Packaging": "3.4.0-rtm-0763", - "NuGet.Frameworks": "3.4.0-rtm-0763", - "NuGet.ProjectModel": "3.4.0-rtm-0763", - + "NuGet.Versioning": "3.5.0-beta-1034", + "NuGet.Packaging": "3.5.0-beta-1034", + "NuGet.Frameworks": "3.5.0-beta-1034", + "NuGet.ProjectModel": "3.5.0-beta-1034", + "Microsoft.DotNet.ProjectModel": { "target": "project" }, diff --git a/test/Microsoft.DotNet.ProjectModel.Tests/LibraryExporterPackageTests.cs b/test/Microsoft.DotNet.ProjectModel.Tests/LibraryExporterPackageTests.cs index b056deedc..2c98adae6 100644 --- a/test/Microsoft.DotNet.ProjectModel.Tests/LibraryExporterPackageTests.cs +++ b/test/Microsoft.DotNet.ProjectModel.Tests/LibraryExporterPackageTests.cs @@ -39,9 +39,9 @@ namespace Microsoft.DotNet.ProjectModel.Tests }); var result = ExportSingle(description); - result.NativeLibraries.Should().HaveCount(1); + result.NativeLibraryGroups.Should().HaveCount(1); - var libraryAsset = result.NativeLibraries.First(); + var libraryAsset = result.NativeLibraryGroups.GetDefaultAssets().First(); libraryAsset.Name.Should().Be("Native"); libraryAsset.Transform.Should().BeNull(); libraryAsset.RelativePath.Should().Be("lib/Native.so"); @@ -83,15 +83,49 @@ namespace Microsoft.DotNet.ProjectModel.Tests }); var result = ExportSingle(description); - result.RuntimeAssemblies.Should().HaveCount(1); + result.RuntimeAssemblyGroups.Should().HaveCount(1); - var libraryAsset = result.RuntimeAssemblies.First(); + var libraryAsset = result.RuntimeAssemblyGroups.GetDefaultAssets().First(); libraryAsset.Name.Should().Be("Native"); libraryAsset.Transform.Should().BeNull(); libraryAsset.RelativePath.Should().Be("ref/Native.dll"); libraryAsset.ResolvedPath.Should().Be(Path.Combine(PackagePath, "ref/Native.dll")); } + [Fact] + public void ExportsPackageRuntimeTargets() + { + var description = CreateDescription( + new LockFileTargetLibrary() + { + RuntimeTargets = new List() + { + new LockFileRuntimeTarget("native/native.dylib", "osx", "native"), + new LockFileRuntimeTarget("lib/Something.OSX.dll", "osx", "runtime") + } + }); + + var result = ExportSingle(description); + result.RuntimeAssemblyGroups.Should().HaveCount(2); + result.RuntimeAssemblyGroups.First(g => g.Runtime == string.Empty).Assets.Should().HaveCount(0); + result.RuntimeAssemblyGroups.First(g => g.Runtime == "osx").Assets.Should().HaveCount(1); + result.NativeLibraryGroups.Should().HaveCount(2); + result.NativeLibraryGroups.First(g => g.Runtime == string.Empty).Assets.Should().HaveCount(0); + result.NativeLibraryGroups.First(g => g.Runtime == "osx").Assets.Should().HaveCount(1); + + var nativeAsset = result.NativeLibraryGroups.GetRuntimeAssets("osx").First(); + nativeAsset.Name.Should().Be("native"); + nativeAsset.Transform.Should().BeNull(); + nativeAsset.RelativePath.Should().Be("native/native.dylib"); + nativeAsset.ResolvedPath.Should().Be(Path.Combine(PackagePath, "native/native.dylib")); + + var runtimeAsset = result.RuntimeAssemblyGroups.GetRuntimeAssets("osx").First(); + runtimeAsset.Name.Should().Be("Something.OSX"); + runtimeAsset.Transform.Should().BeNull(); + runtimeAsset.RelativePath.Should().Be("lib/Something.OSX.dll"); + runtimeAsset.ResolvedPath.Should().Be(Path.Combine(PackagePath, "lib/Something.OSX.dll")); + } + [Fact] public void ExportsSources() { @@ -269,54 +303,6 @@ namespace Microsoft.DotNet.ProjectModel.Tests libraryAsset.ResolvedPath.Should().Be(Path.Combine(PackagePath, "content", "file.any")); } - [Fact] - public void ExportsRuntimeTargets() - { - var win8Native = Path.Combine("native", "win8-x64", "Native.dll"); - var win8Runtime = Path.Combine("runtime", "win8-x64", "Runtime.dll"); - var linuxNative = Path.Combine("native", "linux", "Native.dll"); - - var description = CreateDescription( - new LockFileTargetLibrary() - { - RuntimeTargets = new List() - { - new LockFileRuntimeTarget( - path: win8Native, - runtime: "win8-x64", - assetType: "native" - ), - new LockFileRuntimeTarget( - path: win8Runtime, - runtime: "win8-x64", - assetType: "runtime" - ), - new LockFileRuntimeTarget( - path: linuxNative, - runtime: "linux", - assetType: "native" - ), - } - }); - - var result = ExportSingle(description); - result.RuntimeTargets.Should().HaveCount(2); - - var runtimeTarget = result.RuntimeTargets.Should().Contain(t => t.Runtime == "win8-x64").Subject; - var runtime = runtimeTarget.RuntimeAssemblies.Single(); - runtime.RelativePath.Should().Be(win8Runtime); - runtime.ResolvedPath.Should().Be(Path.Combine(PackagePath, win8Runtime)); - - var native = runtimeTarget.NativeLibraries.Single(); - native.RelativePath.Should().Be(win8Native); - native.ResolvedPath.Should().Be(Path.Combine(PackagePath, win8Native)); - - runtimeTarget = result.RuntimeTargets.Should().Contain(t => t.Runtime == "linux").Subject; - native = runtimeTarget.NativeLibraries.Single(); - native.RelativePath.Should().Be(linuxNative); - native.ResolvedPath.Should().Be(Path.Combine(PackagePath, linuxNative)); - } - private LibraryExport ExportSingle(LibraryDescription description = null) { var rootProject = new Project() diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs index c54e2f2b0..24c8532c5 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs @@ -112,17 +112,19 @@ namespace Microsoft.Extensions.DependencyModel.Tests { var context = Build(runtimeExports: new[] { - Export(PackageDescription("Pack.Age", - servicable: true, - hash: "Hash", - version: new NuGetVersion(1, 2, 3), - dependencies: new[] - { - new LibraryRange("System.Collections", - new VersionRange(new NuGetVersion(2, 1, 2)), - LibraryType.ReferenceAssembly, - LibraryDependencyType.Default) - }), + Export( + PackageDescription( + "Pack.Age", + servicable: true, + hash: "Hash", + version: new NuGetVersion(1, 2, 3), + dependencies: new[] + { + new LibraryRange("System.Collections", + new VersionRange(new NuGetVersion(2, 1, 2)), + LibraryType.ReferenceAssembly, + LibraryDependencyType.Default) + }), resourceAssemblies: new[] { new LibraryResourceAssembly( @@ -130,25 +132,26 @@ namespace Microsoft.Extensions.DependencyModel.Tests "en-US" ) }, - runtimeAssemblies: new[] + runtimeAssemblyGroups: new[] { - new LibraryAsset("Dll", "lib/Pack.Age.dll", ""), + new LibraryAssetGroup( + new LibraryAsset("Dll", "lib/Pack.Age.dll", "")), + new LibraryAssetGroup("win8-x64", + new LibraryAsset("Dll", "win8-x64/Pack.Age.dll", "")) }, - runtimeTargets: new [] + nativeLibraryGroups: new [] { - new LibraryRuntimeTarget( - "win8-x64", - new [] { new LibraryAsset("Dll", "win8-x64/Pack.Age.dll", "") }, - new [] { new LibraryAsset("Dll", "win8-x64/Pack.Age.native.dll", "") } - ) - } - ), - Export(ReferenceAssemblyDescription("System.Collections", - version: new NuGetVersion(3, 3, 3)), - runtimeAssemblies: new[] - { - new LibraryAsset("Dll", "", "System.Collections.dll"), - }) + new LibraryAssetGroup("win8-x64", + new LibraryAsset("Dll", "win8-x64/Pack.Age.native.dll", "")) + }), + Export( + ReferenceAssemblyDescription("System.Collections", + version: new NuGetVersion(3, 3, 3)), + runtimeAssemblyGroups: new[] + { + new LibraryAssetGroup( + new LibraryAsset("Dll", "System.Collections.dll", "System.Collections.dll")) + }) }); context.RuntimeLibraries.Should().HaveCount(2); @@ -159,19 +162,18 @@ namespace Microsoft.Extensions.DependencyModel.Tests lib.Hash.Should().Be("sha512-Hash"); lib.Version.Should().Be("1.2.3"); lib.Dependencies.Should().OnlyContain(l => l.Name == "System.Collections" && l.Version == "3.3.3"); - lib.Assemblies.Should().OnlyContain(l => l.Path == "lib/Pack.Age.dll"); lib.ResourceAssemblies.Should().OnlyContain(l => l.Path == "en-US/Pack.Age.resources.dll" && l.Locale == "en-US"); - var target = lib.RuntimeTargets.Should().Contain(t => t.Runtime == "win8-x64").Subject; - target.Assemblies.Should().OnlyContain(l => l.Path == "win8-x64/Pack.Age.dll"); - target.NativeLibraries.Should().OnlyContain(l => l == "win8-x64/Pack.Age.native.dll"); + lib.RuntimeAssemblyGroups.GetDefaultAssets().Should().OnlyContain(l => l == "lib/Pack.Age.dll"); + lib.RuntimeAssemblyGroups.GetRuntimeAssets("win8-x64").Should().OnlyContain(l => l == "win8-x64/Pack.Age.dll"); + lib.NativeLibraryGroups.GetRuntimeAssets("win8-x64").Should().OnlyContain(l => l == "win8-x64/Pack.Age.native.dll"); var asm = context.RuntimeLibraries.Should().Contain(l => l.Name == "System.Collections").Subject; asm.Type.Should().Be("referenceassembly"); asm.Version.Should().Be("3.3.3"); asm.Hash.Should().BeEmpty(); asm.Dependencies.Should().BeEmpty(); - asm.Assemblies.Should().OnlyContain(l => l.Path == "System.Collections.dll"); + asm.RuntimeAssemblyGroups.GetDefaultAssets().Should().OnlyContain(l => l == "System.Collections.dll"); } [Fact] @@ -292,14 +294,14 @@ namespace Microsoft.Extensions.DependencyModel.Tests private LibraryExport Export( LibraryDescription description, IEnumerable compilationAssemblies = null, - IEnumerable runtimeAssemblies = null, - IEnumerable runtimeTargets = null, + IEnumerable runtimeAssemblyGroups = null, + IEnumerable nativeLibraryGroups = null, IEnumerable resourceAssemblies = null) { return LibraryExportBuilder.Create(description) .WithCompilationAssemblies(compilationAssemblies) - .WithRuntimeAssemblies(runtimeAssemblies) - .WithRuntimeTargets(runtimeTargets) + .WithRuntimeAssemblyGroups(runtimeAssemblyGroups) + .WithNativeLibraryGroups(nativeLibraryGroups) .WithResourceAssemblies(resourceAssemblies) .Build(); } diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs index b611ebd69..dfe5ab3f1 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs @@ -6,6 +6,7 @@ using System.Text; using System.Threading.Tasks; using FluentAssertions; using Xunit; +using System.Diagnostics; namespace Microsoft.Extensions.DependencyModel.Tests { @@ -193,7 +194,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests context.CompileLibraries.Should().HaveCount(2); var project = context.RuntimeLibraries.Should().Contain(l => l.Name == "MyApp").Subject; project.Version.Should().Be("1.0.1"); - project.Assemblies.Should().Contain(a => a.Path == "MyApp.dll"); + project.RuntimeAssemblyGroups.GetDefaultAssets().Should().Contain("MyApp.dll"); project.Type.Should().Be("project"); @@ -202,13 +203,46 @@ namespace Microsoft.Extensions.DependencyModel.Tests package.Hash.Should().Be("HASH-System.Banana"); package.Type.Should().Be("package"); package.Serviceable.Should().Be(false); - package.Assemblies.Should().Contain(a => a.Path == "lib/dotnet5.4/System.Banana.dll"); package.ResourceAssemblies.Should().Contain(a => a.Path == "System.Banana.resources.dll") .Subject.Locale.Should().Be("en-US"); - var target = package.RuntimeTargets.Should().Contain(t => t.Runtime == "win7-x64").Subject; - target.Assemblies.Should().Contain(a => a.Path == "lib/win7/System.Banana.dll"); - target.NativeLibraries.Should().Contain("lib/win7/Banana.dll"); + package.RuntimeAssemblyGroups.GetDefaultAssets().Should().Contain("lib/dotnet5.4/System.Banana.dll"); + package.RuntimeAssemblyGroups.GetRuntimeAssets("win7-x64").Should().Contain("lib/win7/System.Banana.dll"); + package.NativeLibraryGroups.GetRuntimeAssets("win7-x64").Should().Contain("lib/win7/Banana.dll"); + } + + [Fact] + public void ReadsRuntimeTargetPlaceholdersAsEmptyGroups() + { + var context = Read( +@"{ + ""runtimeTarget"": "".NETStandardApp,Version=v1.5"", + ""targets"": { + "".NETStandardApp,Version=v1.5"": { + ""System.Banana/1.0.0"": { + ""runtimeTargets"": { + ""runtime/win7-x64/lib/_._"": { ""assetType"": ""runtime"", ""rid"": ""win7-x64""}, + ""runtime/linux-x64/native/_._"": { ""assetType"": ""native"", ""rid"": ""linux-x64""}, + }, + } + } + }, + ""libraries"":{ + ""System.Banana/1.0.0"": { + ""type"": ""package"", + ""serviceable"": false, + ""sha512"": ""HASH-System.Banana"" + }, + } +}"); + context.CompileLibraries.Should().HaveCount(1); + + var package = context.RuntimeLibraries.Should().Contain(l => l.Name == "System.Banana").Subject; + + package.RuntimeAssemblyGroups.Should().Contain(g => g.Runtime == "win7-x64") + .Which.AssetPaths.Should().BeEmpty(); + package.NativeLibraryGroups.Should().Contain(g => g.Runtime == "linux-x64") + .Which.AssetPaths.Should().BeEmpty(); } [Fact] diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs index ec7ca1a8c..5549d186a 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs @@ -150,16 +150,15 @@ namespace Microsoft.Extensions.DependencyModel.Tests "PackageName", "1.2.3", "HASH", - new [] { RuntimeAssembly.Create("Banana.dll")}, - new [] { "runtimes\\linux\\native\\native.so" }, - new [] { new ResourceAssembly("en-US\\Banana.Resource.dll", "en-US")}, - new [] - { - new RuntimeTarget("win7-x64", - new [] { RuntimeAssembly.Create("Banana.Win7-x64.dll") }, - new [] { "native\\Banana.Win7-x64.so" } - ) + new [] { + new RuntimeAssetGroup(string.Empty, "Banana.dll"), + new RuntimeAssetGroup("win7-x64", "Banana.Win7-x64.dll") }, + new [] { + new RuntimeAssetGroup(string.Empty, "runtimes\\linux\\native\\native.so"), + new RuntimeAssetGroup("win7-x64", "native\\Banana.Win7-x64.so") + }, + new [] { new ResourceAssembly("en-US\\Banana.Resource.dll", "en-US")}, new [] { new Dependency("Fruits.Abstract.dll","2.0.0") }, @@ -229,16 +228,15 @@ namespace Microsoft.Extensions.DependencyModel.Tests "PackageName", "1.2.3", "HASH", - new [] { RuntimeAssembly.Create("Banana.dll")}, - new [] { "native.dll" }, - new ResourceAssembly[] {}, - new [] - { - new RuntimeTarget("win7-x64", - new [] { RuntimeAssembly.Create("Banana.Win7-x64.dll") }, - new [] { "Banana.Win7-x64.so" } - ) + new [] { + new RuntimeAssetGroup(string.Empty, "Banana.dll"), + new RuntimeAssetGroup("win7-x64", "Banana.Win7-x64.dll") }, + new [] { + new RuntimeAssetGroup(string.Empty, "native.dll"), + new RuntimeAssetGroup("win7-x64", "Banana.Win7-x64.so") + }, + new ResourceAssembly[] {}, new [] { new Dependency("Fruits.Abstract.dll","2.0.0") }, @@ -293,10 +291,13 @@ namespace Microsoft.Extensions.DependencyModel.Tests "PackageName", "1.2.3", "HASH", - new [] { RuntimeAssembly.Create("Banana.dll")}, - new [] { "runtimes\\osx\\native\\native.dylib" }, + new [] { + new RuntimeAssetGroup(string.Empty, "Banana.dll") + }, + new [] { + new RuntimeAssetGroup(string.Empty, "runtimes\\osx\\native\\native.dylib") + }, new ResourceAssembly[] {}, - new RuntimeTarget[] {}, new [] { new Dependency("Fruits.Abstract.dll","2.0.0") }, @@ -323,6 +324,58 @@ namespace Microsoft.Extensions.DependencyModel.Tests library.Should().HavePropertyValue("serviceable", true); } + [Fact] + public void WritesPlaceholderRuntimeTargetsForEmptyGroups() + { + var result = Save(Create( + "Target", + "runtime", + true, + runtimeLibraries: new[] + { + new RuntimeLibrary( + "package", + "PackageName", + "1.2.3", + "HASH", + new [] { + new RuntimeAssetGroup("win7-x64"), + new RuntimeAssetGroup("win7-x86", "lib\\x86Support.dll") + }, + new [] { + new RuntimeAssetGroup("linux-x64"), + new RuntimeAssetGroup("osx", "native\\OSXSupport.dylib") + }, + new ResourceAssembly[] { }, + new Dependency[] { }, + true + ), + })); + + // targets + var targets = result.Should().HavePropertyAsObject("targets").Subject; + var target = targets.Should().HavePropertyAsObject("Target").Subject; + var library = target.Should().HavePropertyAsObject("PackageName/1.2.3").Subject; + + var runtimeTargets = library.Should().HavePropertyAsObject("runtimeTargets").Subject; + + var winPlaceholder = runtimeTargets.Should().HavePropertyAsObject("runtime/win7-x64/lib/_._").Subject; + winPlaceholder.Should().HavePropertyValue("rid", "win7-x64"); + winPlaceholder.Should().HavePropertyValue("assetType", "runtime"); + + var winRuntime = runtimeTargets.Should().HavePropertyAsObject("lib/x86Support.dll").Subject; + winPlaceholder.Should().HavePropertyValue("rid", "win7-x64"); + winPlaceholder.Should().HavePropertyValue("assetType", "runtime"); + + var linuxPlaceholder = runtimeTargets.Should().HavePropertyAsObject("runtime/linux-x64/native/_._").Subject; + linuxPlaceholder.Should().HavePropertyValue("rid", "linux-x64"); + linuxPlaceholder.Should().HavePropertyValue("assetType", "native"); + + var osxNative = runtimeTargets.Should().HavePropertyAsObject("native/OSXSupport.dylib").Subject; + osxNative.Should().HavePropertyValue("rid", "osx"); + osxNative.Should().HavePropertyValue("assetType", "native"); + } + [Fact] public void WritesResourceAssembliesForNonPortable() { @@ -337,13 +390,12 @@ namespace Microsoft.Extensions.DependencyModel.Tests "PackageName", "1.2.3", "HASH", - new RuntimeAssembly[] { }, - new string[] { }, + new RuntimeAssetGroup[] { }, + new RuntimeAssetGroup[] { }, new [] { new ResourceAssembly("en-US/Fruits.resources.dll", "en-US") }, - new RuntimeTarget[] { }, new Dependency[] { }, true ), @@ -372,13 +424,12 @@ namespace Microsoft.Extensions.DependencyModel.Tests "PackageName", "1.2.3", "HASH", - new RuntimeAssembly[] { }, - new string[] { }, + new RuntimeAssetGroup[] { }, + new RuntimeAssetGroup[] { }, new [] { new ResourceAssembly("en-US/Fruits.resources.dll", "en-US") }, - new RuntimeTarget[] { }, new Dependency[] { }, true ), @@ -397,7 +448,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests public void WritesCompilationOptions() { var result = Save(Create(compilationOptions: new CompilationOptions( - defines: new[] {"MY", "DEFINES"}, + defines: new[] { "MY", "DEFINES" }, languageVersion: "C#8", platform: "Platform", allowUnsafe: true, @@ -422,7 +473,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests options.Should().HavePropertyValue("languageVersion", "C#8"); options.Should().HavePropertyValue("keyFile", "Key.snk"); options.Should().HaveProperty("defines") - .Subject.Values().Should().BeEquivalentTo(new [] {"MY", "DEFINES" }); + .Subject.Values().Should().BeEquivalentTo(new[] { "MY", "DEFINES" }); } } } \ No newline at end of file diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextLoaderTests.cs b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextLoaderTests.cs index 3b6e88fea..2a996495a 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextLoaderTests.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextLoaderTests.cs @@ -9,7 +9,7 @@ using Xunit; namespace Microsoft.Extensions.DependencyModel.Tests { - public class DependencyContextTests + public class DependencyContextLoaderTests { [Fact] public void MergeMergesLibraries() @@ -125,10 +125,9 @@ namespace Microsoft.Extensions.DependencyModel.Tests name, "1.1.1", "HASH", - new RuntimeAssembly[] { }, - new string[] { }, + new RuntimeAssetGroup[] { }, + new RuntimeAssetGroup[] { }, new ResourceAssembly[] { }, - new RuntimeTarget[] { }, new Dependency[] {}, false); } diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextTests.cs b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextTests.cs new file mode 100644 index 000000000..de0f52256 --- /dev/null +++ b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextTests.cs @@ -0,0 +1,140 @@ +using FluentAssertions; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Extensions.DependencyModel.Tests +{ + public class DependencyContextTests + { + [Theory] + [InlineData("System.Banana.dll", "System.Banana")] + [InlineData("System.Banana.ni.dll", "System.Banana")] + [InlineData("FlibbidyFlob", "FlibbidyFlob")] + public void GetRuntimeAssemblyNamesExtractsCorrectAssemblyName(string path, string expected) + { + var context = new DependencyContext( + ".NETStandard,Version=v1.3", + string.Empty, + isPortable: true, + compilationOptions: CompilationOptions.Default, + compileLibraries: new CompilationLibrary[] { }, + runtimeLibraries: new[] { + new RuntimeLibrary("package", "System.Banana", "1.0.0", "hash", + new [] { + new RuntimeAssetGroup(string.Empty, Path.Combine("lib", path)) + }, + new RuntimeAssetGroup[] { }, + new ResourceAssembly[] { }, + new Dependency[] { }, + serviceable: false) + }, + runtimeGraph: new RuntimeFallbacks[] { }); + + var assets = context.GetDefaultAssemblyNames(); + assets.Should().BeEquivalentTo(expected); + } + + [Fact] + public void GetRuntimeAssemblyNamesReturnsRIDLessAssetsIfNoRIDSpecificAssetsInLibrary() + { + var context = BuildTestContext(); + + var assets = context.GetRuntimeAssemblyNames("win7-x64"); + assets.Should().BeEquivalentTo("System.Banana"); + } + + [Fact] + public void GetRuntimeAssemblyNamesReturnsMostSpecificAssetIfRIDSpecificAssetInLibrary() + { + var context = BuildTestContext(); + + var assets = context.GetRuntimeAssemblyNames("win81-x64"); + assets.Should().BeEquivalentTo("System.Banana"); + } + + [Fact] + public void GetRuntimeAssemblyNamesReturnsEmptyIfEmptyRuntimeGroupPresent() + { + var context = BuildTestContext(); + + var assets = context.GetRuntimeAssemblyNames("win10-x64"); + assets.Should().BeEmpty(); + } + + [Fact] + public void GetRuntimeNativeAssetsReturnsEmptyIfNoGroupsMatch() + { + var context = BuildTestContext(); + + var assets = context.GetRuntimeNativeAssets("win7-x64"); + assets.Should().BeEmpty(); + } + + [Fact] + public void GetRuntimeNativeAssetsReturnsMostSpecificAssetIfRIDSpecificAssetInLibrary() + { + var context = BuildTestContext(); + + var assets = context.GetRuntimeNativeAssets("linux-x64"); + assets.Should().BeEquivalentTo(Path.Combine("runtimes", "linux-x64", "native", "System.Banana.Native.so")); + } + + [Fact] + public void GetRuntimeNativeAssetsReturnsEmptyIfEmptyRuntimeGroupPresent() + { + var context = BuildTestContext(); + + var assets = context.GetRuntimeNativeAssets("rhel-x64"); + assets.Should().BeEmpty(); + } + + private DependencyContext BuildTestContext() + { + return new DependencyContext( + ".NETStandard,Version=v1.3", + string.Empty, + isPortable: true, + compilationOptions: CompilationOptions.Default, + compileLibraries: new[] + { + new CompilationLibrary("package", "System.Banana", "1.0.0", "hash", + new [] { Path.Combine("ref", "netstandard1.3", "System.Banana.dll") }, + new Dependency[] { }, + serviceable: false) + }, + runtimeLibraries: new[] { + new RuntimeLibrary("package", "System.Banana", "1.0.0", "hash", + new [] { + new RuntimeAssetGroup(string.Empty, Path.Combine("lib", "netstandard1.3", "System.Banana.dll")), + new RuntimeAssetGroup("win10"), + new RuntimeAssetGroup("win8", Path.Combine("runtimes", "win8", "lib", "netstandard1.3", "System.Banana.dll")) + }, + new [] { + new RuntimeAssetGroup("rhel"), + new RuntimeAssetGroup("linux-x64", Path.Combine("runtimes", "linux-x64", "native", "System.Banana.Native.so")), + new RuntimeAssetGroup("osx-x64", Path.Combine("runtimes", "osx-x64", "native", "System.Banana.Native.dylib")), + + // Just here to test we don't fall back through it for the other cases. There's + // no such thing as a "unix" native asset since there's no common executable format :) + new RuntimeAssetGroup("unix", Path.Combine("runtimes", "osx-x64", "native", "System.Banana.Native")) + }, + new ResourceAssembly[] { }, + new Dependency[] { }, + serviceable: false) + }, + runtimeGraph: new[] { + new RuntimeFallbacks("win10-x64", "win10", "win81-x64", "win81", "win8-x64", "win8", "win7-x64", "win7", "win-x64", "win", "any", "base"), + new RuntimeFallbacks("win81-x64", "win81", "win8-x64", "win8", "win7-x64", "win7", "win-x64", "win", "any", "base"), + new RuntimeFallbacks("win8-x64", "win8", "win7-x64", "win7", "win-x64", "win", "any", "base"), + new RuntimeFallbacks("win7-x64", "win7", "win-x64", "win", "any", "base"), + new RuntimeFallbacks("ubuntu-x64", "ubuntu", "linux-x64", "linux", "unix", "any", "base"), + new RuntimeFallbacks("rhel-x64", "rhel", "linux-x64", "linux", "unix", "any", "base"), + new RuntimeFallbacks("osx-x64", "osx", "unix", "any", "base"), + }); + } + } +} diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/ReferenceAssemblyResolverTests.cs b/test/Microsoft.Extensions.DependencyModel.Tests/ReferenceAssemblyResolverTests.cs index dbaf6589d..2b4f53d7d 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/ReferenceAssemblyResolverTests.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/ReferenceAssemblyResolverTests.cs @@ -36,7 +36,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests { var runtime = new Mock(); runtime.SetupGet(r => r.OperatingSystemPlatform).Returns(Platform.Windows); - + var environment = EnvironmentMockBuilder.Create() .AddVariable("DOTNET_REFERENCE_ASSEMBLIES_PATH", ReferencePath) .Build(); diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/RuntimeAssemblyTests.cs b/test/Microsoft.Extensions.DependencyModel.Tests/RuntimeAssemblyTests.cs deleted file mode 100644 index a4a251381..000000000 --- a/test/Microsoft.Extensions.DependencyModel.Tests/RuntimeAssemblyTests.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Threading.Tasks; -using FluentAssertions; -using Xunit; - -namespace Microsoft.Extensions.DependencyModel.Tests -{ - public class RuntimeAssemblyTests - { - [Fact] - public void UsesFileNameAsAssemblyNameInCreate() - { - var assembly = RuntimeAssembly.Create("path/to/System.Collections.dll"); - assembly.Name.Name.Should().Be("System.Collections"); - } - - [Fact] - public void TrimsDotNiFromDllNames() - { - var assembly = RuntimeAssembly.Create("path/to/System.Collections.ni.dll"); - assembly.Name.Name.Should().Be("System.Collections"); - } - } -} diff --git a/test/dotnet-test.Tests/GivenThatWeWantToRunTestsInTheConsole.cs b/test/dotnet-test.Tests/GivenThatWeWantToRunTestsInTheConsole.cs index 435cd6c51..d4e577334 100644 --- a/test/dotnet-test.Tests/GivenThatWeWantToRunTestsInTheConsole.cs +++ b/test/dotnet-test.Tests/GivenThatWeWantToRunTestsInTheConsole.cs @@ -32,7 +32,8 @@ namespace Microsoft.Dotnet.Tools.Test.Tests } //ISSUE https://github.com/dotnet/cli/issues/1935 - [WindowsOnlyFact] + // This fact technically succeeds on Windows, but it causes a crash dialog to pop, which interrupts the build. + //[WindowsOnlyFact] public void It_returns_a_failure_when_it_fails_to_run_the_tests() { var testCommand = new DotnetTestCommand(); diff --git a/tools/MultiProjectValidator/Program.cs b/tools/MultiProjectValidator/Program.cs index 1acd9fbf2..d82d5da0f 100644 --- a/tools/MultiProjectValidator/Program.cs +++ b/tools/MultiProjectValidator/Program.cs @@ -27,7 +27,7 @@ namespace MultiProjectValidator { projects = ProjectLoader.Load(rootPath); } - catch(Exception e) + catch(Exception) { Console.WriteLine("Failed to load projects from path: " + rootPath); return 1; diff --git a/tools/RuntimeGraphGenerator/project.json b/tools/RuntimeGraphGenerator/project.json index 9719346de..b58197748 100644 --- a/tools/RuntimeGraphGenerator/project.json +++ b/tools/RuntimeGraphGenerator/project.json @@ -4,8 +4,8 @@ "emitEntryPoint": true }, "dependencies": { - "NuGet.RuntimeModel": "3.4.0-rtm-0763", - "NuGet.Versioning": "3.4.0-rtm-0763", + "NuGet.RuntimeModel": "3.5.0-beta-1034", + "NuGet.Versioning": "3.5.0-beta-1034", "System.CommandLine": "0.1.0-e160119-1", "System.Runtime.Serialization.Json": "1.0.0-rc2-23911", "Microsoft.DotNet.ProjectModel": "1.0.0-*",