diff --git a/src/Microsoft.DotNet.ProjectModel/Graph/LockFileReader.cs b/src/Microsoft.DotNet.ProjectModel/Graph/LockFileReader.cs index 8e432d9c1..1d76a320a 100644 --- a/src/Microsoft.DotNet.ProjectModel/Graph/LockFileReader.cs +++ b/src/Microsoft.DotNet.ProjectModel/Graph/LockFileReader.cs @@ -13,7 +13,7 @@ using NuGet.Versioning; namespace Microsoft.DotNet.ProjectModel.Graph { - public static class LockFileReader + internal static class LockFileReader { public static LockFile Read(string filePath) { diff --git a/src/Microsoft.DotNet.ProjectModel/ProjectContext.cs b/src/Microsoft.DotNet.ProjectModel/ProjectContext.cs index 8166c9b92..1b54e36ad 100644 --- a/src/Microsoft.DotNet.ProjectModel/ProjectContext.cs +++ b/src/Microsoft.DotNet.ProjectModel/ProjectContext.cs @@ -69,7 +69,7 @@ namespace Microsoft.DotNet.ProjectModel /// public static ProjectContext Create(string projectPath, NuGetFramework framework, IEnumerable runtimeIdentifiers) { - if(projectPath.EndsWith(Project.FileName)) + if (projectPath.EndsWith(Project.FileName)) { projectPath = Path.GetDirectoryName(projectPath); } @@ -85,13 +85,13 @@ namespace Microsoft.DotNet.ProjectModel /// public static IEnumerable CreateContextForEachFramework(string projectPath) { - if(!projectPath.EndsWith(Project.FileName)) + if (!projectPath.EndsWith(Project.FileName)) { projectPath = Path.Combine(projectPath, Project.FileName); } var project = ProjectReader.GetProject(projectPath); - foreach(var framework in project.GetTargetFrameworks()) + foreach (var framework in project.GetTargetFrameworks()) { yield return new ProjectContextBuilder() .WithProject(project) @@ -99,6 +99,23 @@ namespace Microsoft.DotNet.ProjectModel .Build(); } } + + /// + /// Creates a project context for each target located in the project at + /// + public static IEnumerable CreateContextForEachTarget(string projectPath) + { + if (!projectPath.EndsWith(Project.FileName)) + { + projectPath = Path.Combine(projectPath, Project.FileName); + } + var project = ProjectReader.GetProject(projectPath); + + return new ProjectContextBuilder() + .WithProject(project) + .BuildAllTargets(); + } + public string GetAssemblyPath(string buildConfiguration) { return Path.Combine( @@ -123,4 +140,4 @@ namespace Microsoft.DotNet.ProjectModel ProjectModel.RuntimeIdentifier.Current); } } -} \ No newline at end of file +} diff --git a/src/Microsoft.DotNet.ProjectModel/ProjectContextBuilder.cs b/src/Microsoft.DotNet.ProjectModel/ProjectContextBuilder.cs index 0101fc7fa..9200fa167 100644 --- a/src/Microsoft.DotNet.ProjectModel/ProjectContextBuilder.cs +++ b/src/Microsoft.DotNet.ProjectModel/ProjectContextBuilder.cs @@ -37,6 +37,12 @@ namespace Microsoft.DotNet.ProjectModel private Func LockFileResolver { get; set; } + public ProjectContextBuilder() + { + ProjectResolver = ResolveProject; + LockFileResolver = ResolveLockFile; + } + public ProjectContextBuilder WithLockFile(LockFile lockFile) { LockFile = lockFile; @@ -103,11 +109,28 @@ namespace Microsoft.DotNet.ProjectModel return this; } + public IEnumerable BuildAllTargets() + { + ProjectDirectory = Project?.ProjectDirectory ?? ProjectDirectory; + EnsureProjectLoaded(); + LockFile = LockFile ?? LockFileResolver(ProjectDirectory); + + if (LockFile != null) + { + foreach (var target in LockFile.Targets) + { + yield return new ProjectContextBuilder() + .WithProject(Project) + .WithLockFile(LockFile) + .WithTargetFramework(target.TargetFramework) + .WithRuntimeIdentifiers(new[] { target.RuntimeIdentifier }) + .Build(); + } + } + } + public ProjectContext Build() { - ProjectResolver = ProjectResolver ?? ResolveProject; - LockFileResolver = LockFileResolver ?? (projectDir => LockFileReader.Read(Path.Combine(projectDir, LockFile.FileName))); - ProjectDirectory = Project?.ProjectDirectory ?? ProjectDirectory; if (GlobalSettings == null) @@ -129,12 +152,7 @@ namespace Microsoft.DotNet.ProjectModel EnsureProjectLoaded(); - var projectLockJsonPath = Path.Combine(ProjectDirectory, LockFile.FileName); - - if (LockFile == null && File.Exists(projectLockJsonPath)) - { - LockFile = LockFileResolver(ProjectDirectory); - } + LockFile = LockFile ?? LockFileResolver(ProjectDirectory); var validLockFile = true; string lockFileValidationMessage = null; @@ -408,6 +426,14 @@ namespace Microsoft.DotNet.ProjectModel } } + private static LockFile ResolveLockFile(string projectDir) + { + var projectLockJsonPath = Path.Combine(projectDir, LockFile.FileName); + return File.Exists(projectLockJsonPath) ? + LockFileReader.Read(Path.Combine(projectDir, LockFile.FileName)) : + null; + } + private struct LibraryKey { public LibraryKey(string name) : this(name, LibraryType.Unspecified) diff --git a/src/Microsoft.DotNet.Tools.Publish/Program.cs b/src/Microsoft.DotNet.Tools.Publish/Program.cs index 24ad89bb5..a3be3cbd2 100644 --- a/src/Microsoft.DotNet.Tools.Publish/Program.cs +++ b/src/Microsoft.DotNet.Tools.Publish/Program.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using Microsoft.Dnx.Runtime.Common.CommandLine; using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.ProjectModel; @@ -33,10 +34,17 @@ namespace Microsoft.DotNet.Tools.Publish app.OnExecute(() => { - if (framework.HasValue() && IsUnsupportedFramework(framework.Value())) + NuGetFramework nugetframework = null; + + if (framework.HasValue()) { - Reporter.Output.WriteLine($"Unsupported framework {framework.Value()}.".Red()); - return 1; + nugetframework = NuGetFramework.Parse(framework.Value()); + + if (nugetframework.IsUnsupported) + { + Reporter.Output.WriteLine($"Unsupported framework {framework.Value()}.".Red()); + return 1; + } } // TODO: Remove this once xplat publish is enabled. @@ -52,22 +60,13 @@ namespace Microsoft.DotNet.Tools.Publish path = Directory.GetCurrentDirectory(); } - // get the lock file - var projectLockJsonPath = GetProjectLockFile(path); - if (!File.Exists(projectLockJsonPath)) - { - Reporter.Output.WriteLine($"Unable to locate {LockFile.FileName} for project '{project.Value}'".Red()); - Reporter.Output.WriteLine($"Run 'dotnet restore' before calling 'dotnet publish'".Red()); - return 1; - } + var projectContexts = ProjectContext.CreateContextForEachTarget(path); + projectContexts = GetMatchingProjectContexts(projectContexts, nugetframework, runtime.Value()); - var lockFile = LockFileReader.Read(projectLockJsonPath); - var lockFileTargets = GetMatchingTargets(lockFile, framework.Value(), runtime.Value()); - - if(lockFileTargets.Count() == 0) + if (projectContexts.Count() == 0) { string errMsg = $"'{project.Value}' cannot be published"; - if(framework.HasValue() || runtime.HasValue()) + if (framework.HasValue() || runtime.HasValue()) { errMsg += $" for '{framework.Value()}' '{runtime.Value()}'"; } @@ -77,9 +76,9 @@ namespace Microsoft.DotNet.Tools.Publish } int result = 0; - foreach(var target in lockFileTargets) + foreach (var projectContext in projectContexts) { - result += Publish(target.TargetFramework, target.RuntimeIdentifier, path, output.Value(), configuration.Value() ?? Constants.DefaultConfiguration); + result += Publish(projectContext, output.Value(), configuration.Value() ?? Constants.DefaultConfiguration); } return result; @@ -110,38 +109,20 @@ namespace Microsoft.DotNet.Tools.Publish return true; } - private static bool IsUnsupportedFramework(string framework) + // return the matching framework/runtime ProjectContext. + // if 'nugetframework' or 'runtime' is null or empty then it matches with any. + private static IEnumerable GetMatchingProjectContexts(IEnumerable contexts, NuGetframework framework, string runtimeIdentifier) { - return NuGetFramework.Parse(framework).Equals(NuGetFramework.UnsupportedFramework); - } - - private static string GetProjectDirectory(string project) - { - return project.ToLower().EndsWith(Project.FileName) ? - Path.GetDirectoryName(project) : - project; - } - - private static string GetProjectLockFile(string project) - { - string projectDir = GetProjectDirectory(project); - return Path.Combine(projectDir, LockFile.FileName); - } - - // return the matching framework/runtime targets in the lock file - // if 'framework' or 'runtime' is null or empty then it matches with any. - private static IEnumerable GetMatchingTargets(LockFile lockFile, string framework, string runtime) - { - var lockFileTargets = lockFile.Targets.Where(target => + var matchingContexts = contexts.Where(context => { - if (target.TargetFramework == null || string.IsNullOrEmpty(target.RuntimeIdentifier)) + if (context.TargetFramework == null || string.IsNullOrEmpty(context.RuntimeIdentifier)) { return false; } - if (string.IsNullOrEmpty(runtime) || runtime.Equals(target.RuntimeIdentifier)) + if (string.IsNullOrEmpty(runtimeIdentifier) || runtimeIdentifier.Equals(context.RuntimeIdentifier)) { - if (string.IsNullOrEmpty(framework) || NuGetFramework.Parse(framework).Equals(target.TargetFramework)) + if (framework == null || framework.Equals(context.TargetFramework)) { return true; } @@ -150,24 +131,16 @@ namespace Microsoft.DotNet.Tools.Publish return false; }); - return lockFileTargets; - } - - private static int Publish(NuGetFramework framework, string runtimeIdentifier, string projectPath, string outputPath, string configuration) - { - // Load project context and publish it - var runtimeIdentifiers = new[] { runtimeIdentifier }; - var context = ProjectContext.Create(projectPath, framework, runtimeIdentifiers); - - if (string.IsNullOrEmpty(context.RuntimeIdentifier)) - { - Reporter.Output.WriteLine($"{context.RootProject.Identity} cannot be published for {context.TargetFramework.DotNetFrameworkName}/{runtimeIdentifier}.".Red()); - return 1; - } - - return Publish(context, outputPath, configuration); + return matchingContexts; } + /// + /// Publish the project for given 'framework (ex - dnxcore50)' and 'runtimeID (ex - win7-x64)' + /// + /// project that is to be published + /// Location of published files + /// Debug or Release + /// Return 0 if successful else return non-zero private static int Publish(ProjectContext context, string outputPath, string configuration) { Reporter.Output.WriteLine($"Publishing {context.RootProject.Identity.Name.Yellow()} for {context.TargetFramework.DotNetFrameworkName.Yellow()}/{context.RuntimeIdentifier.Yellow()}"); @@ -191,7 +164,7 @@ namespace Microsoft.DotNet.Tools.Publish } // Compile the project (and transitively, all it's dependencies) - var result = Command.Create("dotnet-compile", + var result = Command.Create("dotnet-compile", $"--framework \"{context.TargetFramework.DotNetFrameworkName}\" " + $"--output \"{outputPath}\" " + $"--configuration \"{configuration}\" " +