Merge branch 'master' of https://github.com/dotnet/cli into publish-tests2
This commit is contained in:
commit
55b9697b74
61 changed files with 1632 additions and 782 deletions
|
@ -11,6 +11,7 @@ namespace Microsoft.DotNet.Cli.Utils
|
|||
{
|
||||
internal static class Constants
|
||||
{
|
||||
public static readonly string ProjectFileName = "project.json";
|
||||
public static readonly string ExeSuffix = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".exe" : string.Empty;
|
||||
|
||||
// Priority order of runnable suffixes to look for and run
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"shared": "**/*.cs",
|
||||
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.0.0-rc2-23608",
|
||||
"NETStandard.Library": "1.0.0-rc2-23616",
|
||||
"Microsoft.DotNet.ProjectModel": "1.0.0"
|
||||
},
|
||||
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
"emitEntryPoint": true
|
||||
},
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.0.0-rc2-23608",
|
||||
"System.Linq": "4.0.1-rc2-23608",
|
||||
"NETStandard.Library": "1.0.0-rc2-23616",
|
||||
|
||||
"Microsoft.DotNet.Cli.Utils": {
|
||||
"type": "build",
|
||||
|
|
|
@ -6,9 +6,9 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using System.IO;
|
||||
using System.Runtime.Versioning;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
|
||||
namespace Microsoft.Dotnet.Cli.Compiler.Common
|
||||
|
@ -26,7 +26,8 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common
|
|||
[typeof(AssemblyVersionAttribute)] = EscapeCharacters(metadata.AssemblyVersion?.ToString()),
|
||||
[typeof(AssemblyInformationalVersionAttribute)] = EscapeCharacters(metadata.InformationalVersion),
|
||||
[typeof(AssemblyCultureAttribute)] = EscapeCharacters(metadata.Culture),
|
||||
[typeof(NeutralResourcesLanguageAttribute)] = EscapeCharacters(metadata.NeutralLanguage)
|
||||
[typeof(NeutralResourcesLanguageAttribute)] = EscapeCharacters(metadata.NeutralLanguage),
|
||||
[typeof(TargetFrameworkAttribute)] = EscapeCharacters(metadata.TargetFramework)
|
||||
};
|
||||
|
||||
var existingAttributes = new List<Type>();
|
||||
|
|
|
@ -5,6 +5,8 @@ using Microsoft.DotNet.ProjectModel;
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.CommandLine;
|
||||
using System.Linq;
|
||||
using NuGet.Frameworks;
|
||||
|
||||
namespace Microsoft.Dotnet.Cli.Compiler.Common
|
||||
{
|
||||
|
@ -26,6 +28,8 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common
|
|||
|
||||
private const string NeutralCultureOptionName = "neutral-language";
|
||||
|
||||
private const string TargetFrameworkOptionName = "target-framework";
|
||||
|
||||
public string Title { get; set; }
|
||||
|
||||
public string Description { get; set; }
|
||||
|
@ -42,8 +46,22 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common
|
|||
|
||||
public string NeutralLanguage { get; set; }
|
||||
|
||||
public static AssemblyInfoOptions CreateForProject(Project project)
|
||||
public string TargetFramework { get; set; }
|
||||
|
||||
public static AssemblyInfoOptions CreateForProject(ProjectContext context)
|
||||
{
|
||||
var project = context.ProjectFile;
|
||||
NuGetFramework targetFramework = null;
|
||||
// force .NETFramework instead of DNX
|
||||
if (context.TargetFramework.IsDesktop())
|
||||
{
|
||||
targetFramework = new NuGetFramework(FrameworkConstants.FrameworkIdentifiers.Net, context.TargetFramework.Version);
|
||||
}
|
||||
else
|
||||
{
|
||||
targetFramework = context.TargetFramework;
|
||||
}
|
||||
|
||||
return new AssemblyInfoOptions()
|
||||
{
|
||||
AssemblyVersion = project.Version?.Version.ToString(),
|
||||
|
@ -52,7 +70,8 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common
|
|||
Copyright = project.Copyright,
|
||||
Description = project.Description,
|
||||
Title = project.Title,
|
||||
NeutralLanguage = project.Language
|
||||
NeutralLanguage = project.Language,
|
||||
TargetFramework = targetFramework.DotNetFrameworkName
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -66,22 +85,25 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common
|
|||
string copyright = null;
|
||||
string culture = null;
|
||||
string neutralCulture = null;
|
||||
string targetFramework = null;
|
||||
|
||||
syntax.DefineOption(AssemblyVersionOptionName, ref version, "Assembly version");
|
||||
syntax.DefineOption(AssemblyVersionOptionName, ref version, UnescapeNewlines, "Assembly version");
|
||||
|
||||
syntax.DefineOption(TitleOptionName, ref title, "Assembly title");
|
||||
syntax.DefineOption(TitleOptionName, ref title, UnescapeNewlines, "Assembly title");
|
||||
|
||||
syntax.DefineOption(DescriptionOptionName, ref description, "Assembly description");
|
||||
syntax.DefineOption(DescriptionOptionName, ref description, UnescapeNewlines, "Assembly description");
|
||||
|
||||
syntax.DefineOption(CopyrightOptionName, ref copyright, "Assembly copyright");
|
||||
syntax.DefineOption(CopyrightOptionName, ref copyright, UnescapeNewlines, "Assembly copyright");
|
||||
|
||||
syntax.DefineOption(NeutralCultureOptionName, ref neutralCulture, "Assembly neutral culture");
|
||||
syntax.DefineOption(NeutralCultureOptionName, ref neutralCulture, UnescapeNewlines, "Assembly neutral culture");
|
||||
|
||||
syntax.DefineOption(CultureOptionName, ref culture, "Assembly culture");
|
||||
syntax.DefineOption(CultureOptionName, ref culture, UnescapeNewlines, "Assembly culture");
|
||||
|
||||
syntax.DefineOption(InformationalVersionOptionName, ref informationalVersion, "Assembly informational version");
|
||||
syntax.DefineOption(InformationalVersionOptionName, ref informationalVersion, UnescapeNewlines, "Assembly informational version");
|
||||
|
||||
syntax.DefineOption(AssemblyFileVersionOptionName, ref fileVersion, "Assembly title");
|
||||
syntax.DefineOption(AssemblyFileVersionOptionName, ref fileVersion, UnescapeNewlines, "Assembly title");
|
||||
|
||||
syntax.DefineOption(TargetFrameworkOptionName, ref targetFramework, UnescapeNewlines, "Assembly target framework");
|
||||
|
||||
return new AssemblyInfoOptions()
|
||||
{
|
||||
|
@ -91,7 +113,8 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common
|
|||
NeutralLanguage = neutralCulture,
|
||||
Description = description,
|
||||
InformationalVersion = informationalVersion,
|
||||
Title = title
|
||||
Title = title,
|
||||
TargetFramework = targetFramework
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -131,13 +154,26 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common
|
|||
{
|
||||
options.Add(FormatOption(NeutralCultureOptionName, assemblyInfoOptions.NeutralLanguage));
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(assemblyInfoOptions.TargetFramework))
|
||||
{
|
||||
options.Add(FormatOption(TargetFrameworkOptionName, assemblyInfoOptions.TargetFramework));
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
private static string FormatOption(string optionName, string value)
|
||||
{
|
||||
return $"--{optionName}:{value}";
|
||||
return $"--{optionName}:{EscapeNewlines(value)}";
|
||||
}
|
||||
|
||||
private static string UnescapeNewlines(string text)
|
||||
{
|
||||
return text.Replace("\\r", "\r").Replace("\\n", "\n");
|
||||
}
|
||||
private static string EscapeNewlines(string text)
|
||||
{
|
||||
return text.Replace("\r", "\\r").Replace("\n", "\\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,8 @@
|
|||
"version": "1.0.0-*",
|
||||
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.0.0-rc2-23608",
|
||||
"System.Linq": "4.0.1-rc2-23608",
|
||||
"System.Reflection": "4.0.10-rc2-23608",
|
||||
"System.Reflection": "4.0.10-rc2-23616",
|
||||
"NETStandard.Library": "1.0.0-rc2-23616",
|
||||
"System.CommandLine": "0.1.0-*",
|
||||
"Microsoft.CodeAnalysis.CSharp": "1.1.1",
|
||||
"Microsoft.DotNet.ProjectModel": "1.0.0-*",
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"version": "1.0.0-*",
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.0.0-rc2-23616",
|
||||
"Microsoft.DotNet.ProjectModel": "1.0.0-*",
|
||||
"NETStandard.Library": "1.0.0-rc2-23608",
|
||||
"System.Runtime.Loader": "4.0.0-rc2-23608"
|
||||
"System.Runtime.Loader": "4.0.0-rc2-23616"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnxcore50": { }
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"version": "1.0.0-*",
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.0.0-rc2-23616",
|
||||
"Microsoft.DotNet.ProjectModel": "1.0.0-*",
|
||||
"Microsoft.CodeAnalysis.CSharp.Workspaces": "1.1.0-*"
|
||||
},
|
||||
|
|
|
@ -2,17 +2,16 @@
|
|||
"version": "1.0.0-*",
|
||||
"description": "Types to model a .NET Project",
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.0.0-rc2-23608",
|
||||
"System.Linq": "4.0.1-rc2-23608",
|
||||
"System.Threading.Thread": "4.0.0-rc2-23608",
|
||||
"System.Runtime.Loader": "4.0.0-rc2-23608",
|
||||
"System.Dynamic.Runtime": "4.0.11-rc2-23608",
|
||||
"System.Security.Cryptography.Algorithms": "4.0.0-rc2-23608",
|
||||
"Microsoft.CSharp": "4.0.1-rc2-23608",
|
||||
"System.Xml.XDocument": "4.0.11-rc2-23608",
|
||||
"NETStandard.Library": "1.0.0-rc2-23616",
|
||||
"System.Threading.Thread": "4.0.0-rc2-23616",
|
||||
"System.Runtime.Loader": "4.0.0-rc2-23616",
|
||||
"System.Dynamic.Runtime": "4.0.11-rc2-23616",
|
||||
"System.Security.Cryptography.Algorithms": "4.0.0-rc2-23616",
|
||||
"Microsoft.CSharp": "4.0.1-rc2-23616",
|
||||
"System.Xml.XDocument": "4.0.11-rc2-23616",
|
||||
"NuGet.Packaging": "3.3.0-*",
|
||||
|
||||
"Microsoft.Extensions.FileSystemGlobbing": "1.0.0-rc2-15791",
|
||||
"Microsoft.Extensions.FileSystemGlobbing": "1.0.0-rc2-15882",
|
||||
"Microsoft.Extensions.JsonParser.Sources": {
|
||||
"type": "build",
|
||||
"version": "1.0.0-*"
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
},
|
||||
|
||||
"dependencies": {
|
||||
"NETStandard.Library" : "1.0.0-rc2-23608",
|
||||
"Microsoft.NETCore.Runtime": "1.0.1-beta-23504"
|
||||
"NETStandard.Library" : "1.0.0-rc2-23616"
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
|
|
|
@ -5,10 +5,9 @@
|
|||
"emitEntryPoint": true
|
||||
},
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.0.0-rc2-23608",
|
||||
"System.Linq": "4.0.1-rc2-23608",
|
||||
"NETStandard.Library": "1.0.0-rc2-23616",
|
||||
|
||||
"Microsoft.Net.Compilers.netcore": "1.2.0-beta-20151117-04",
|
||||
"Microsoft.Net.Compilers.netcore": "1.2.0-beta-20151215-01",
|
||||
|
||||
"Microsoft.DotNet.Cli.Utils": {
|
||||
"type": "build",
|
||||
|
|
|
@ -74,7 +74,7 @@ namespace Microsoft.DotNet.Tools.Compiler.Native
|
|||
}
|
||||
else if (config.OS == OSMode.Mac)
|
||||
{
|
||||
throw new NotImplementedException("Mac RyuJit not supported");
|
||||
stepList.Add(new MacRyuJitCompileStep(config));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -102,18 +102,6 @@ namespace Microsoft.DotNet.Tools.Compiler.Native
|
|||
.ForwardStdOut()
|
||||
.Execute();
|
||||
|
||||
// Needs System.Native.so in output
|
||||
var sharedLibPath = Path.Combine(config.IlcPath, "System.Native.so");
|
||||
var outputSharedLibPath = Path.Combine(config.OutputDirectory, "System.Native.so");
|
||||
try
|
||||
{
|
||||
File.Copy(sharedLibPath, outputSharedLibPath);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Reporter.Error.WriteLine("Unable to copy System.Native.so to output");
|
||||
}
|
||||
|
||||
return result.ExitCode;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using Microsoft.Dnx.Runtime.Common.CommandLine;
|
||||
using Microsoft.DotNet.Cli.Utils;
|
||||
using Microsoft.DotNet.Tools.Common;
|
||||
|
||||
namespace Microsoft.DotNet.Tools.Compiler.Native
|
||||
{
|
||||
public class MacLinkStep : IPlatformNativeStep
|
||||
{
|
||||
public int Invoke()
|
||||
{
|
||||
throw new NotImplementedException("Mac linker Not supported yet.");
|
||||
}
|
||||
|
||||
public bool CheckPreReqs()
|
||||
{
|
||||
throw new NotImplementedException("Mac linker Not supported yet.");
|
||||
}
|
||||
|
||||
public string DetermineOutputFile(NativeCompileSettings config)
|
||||
{
|
||||
throw new NotImplementedException("Mac linker Not supported yet.");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using Microsoft.Dnx.Runtime.Common.CommandLine;
|
||||
using Microsoft.DotNet.Cli.Utils;
|
||||
using Microsoft.DotNet.Tools.Common;
|
||||
|
||||
namespace Microsoft.DotNet.Tools.Compiler.Native
|
||||
{
|
||||
public class MacRyuJitCompileStep : IPlatformNativeStep
|
||||
{
|
||||
private readonly string CompilerName = "clang";
|
||||
private readonly string InputExtension = ".obj";
|
||||
|
||||
private readonly string CompilerOutputExtension = "";
|
||||
|
||||
// TODO: debug/release support
|
||||
private readonly string cflags = "-g -lstdc++ -Wno-invalid-offsetof -pthread -ldl -lm -liconv";
|
||||
|
||||
private readonly string[] libs = new string[]
|
||||
{
|
||||
"libbootstrapper.a",
|
||||
"libRuntime.a",
|
||||
"libSystem.Private.CoreLib.Native.a"
|
||||
};
|
||||
|
||||
private readonly string[] appdeplibs = new string[]
|
||||
{
|
||||
"libSystem.Native.a"
|
||||
};
|
||||
|
||||
|
||||
private string CompilerArgStr { get; set; }
|
||||
private NativeCompileSettings config;
|
||||
|
||||
public MacRyuJitCompileStep(NativeCompileSettings config)
|
||||
{
|
||||
this.config = config;
|
||||
InitializeArgs(config);
|
||||
}
|
||||
|
||||
public int Invoke()
|
||||
{
|
||||
var result = InvokeCompiler();
|
||||
if (result != 0)
|
||||
{
|
||||
Reporter.Error.WriteLine("Compilation of intermediate files failed.");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool CheckPreReqs()
|
||||
{
|
||||
// TODO check for clang
|
||||
return true;
|
||||
}
|
||||
|
||||
private void InitializeArgs(NativeCompileSettings config)
|
||||
{
|
||||
var argsList = new List<string>();
|
||||
|
||||
// Flags
|
||||
argsList.Add(cflags);
|
||||
|
||||
// Add Stubs
|
||||
argsList.Add("-I "+Path.Combine(config.AppDepSDKPath, "CPPSdk/osx.10.10"));
|
||||
argsList.Add("-I "+Path.Combine(config.AppDepSDKPath, "CPPSdk"));
|
||||
argsList.Add(Path.Combine(config.AppDepSDKPath, "CPPSdk/osx.10.10/osxstubs.cpp"));
|
||||
|
||||
// Input File
|
||||
var inLibFile = DetermineInFile(config);
|
||||
argsList.Add("-Xlinker "+inLibFile);
|
||||
|
||||
// Libs
|
||||
foreach (var lib in libs)
|
||||
{
|
||||
var libPath = Path.Combine(config.IlcPath, lib);
|
||||
argsList.Add("-Xlinker "+libPath);
|
||||
}
|
||||
|
||||
// AppDep Libs
|
||||
var baseAppDepLibPath = Path.Combine(config.AppDepSDKPath, "CPPSdk/osx.10.10", config.Architecture.ToString());
|
||||
foreach (var lib in appdeplibs)
|
||||
{
|
||||
var appDepLibPath = Path.Combine(baseAppDepLibPath, lib);
|
||||
argsList.Add("-Xlinker "+appDepLibPath);
|
||||
}
|
||||
|
||||
// Output
|
||||
var libOut = DetermineOutputFile(config);
|
||||
argsList.Add($"-o \"{libOut}\"");
|
||||
|
||||
this.CompilerArgStr = string.Join(" ", argsList);
|
||||
}
|
||||
|
||||
private int InvokeCompiler()
|
||||
{
|
||||
var result = Command.Create(CompilerName, CompilerArgStr)
|
||||
.ForwardStdErr()
|
||||
.ForwardStdOut()
|
||||
.Execute();
|
||||
|
||||
return result.ExitCode;
|
||||
}
|
||||
|
||||
private string DetermineInFile(NativeCompileSettings config)
|
||||
{
|
||||
var intermediateDirectory = config.IntermediateDirectory;
|
||||
|
||||
var filename = Path.GetFileNameWithoutExtension(config.InputManagedAssemblyPath);
|
||||
|
||||
var infile = Path.Combine(intermediateDirectory, filename + InputExtension);
|
||||
|
||||
return infile;
|
||||
}
|
||||
|
||||
public string DetermineOutputFile(NativeCompileSettings config)
|
||||
{
|
||||
var intermediateDirectory = config.OutputDirectory;
|
||||
|
||||
var filename = Path.GetFileNameWithoutExtension(config.InputManagedAssemblyPath);
|
||||
|
||||
var outfile = Path.Combine(intermediateDirectory, filename + CompilerOutputExtension);
|
||||
|
||||
return outfile;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,8 +5,7 @@
|
|||
"emitEntryPoint": true
|
||||
},
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.0.0-rc2-23608",
|
||||
"System.Linq": "4.0.1-rc2-23608",
|
||||
"NETStandard.Library": "1.0.0-rc2-23616",
|
||||
|
||||
"Microsoft.DotNet.Cli.Utils": {
|
||||
"type": "build",
|
||||
|
|
|
@ -279,9 +279,6 @@ namespace Microsoft.DotNet.Tools.Compiler
|
|||
return false;
|
||||
}
|
||||
|
||||
// Dump dependency data
|
||||
ShowDependencyInfo(dependencies);
|
||||
|
||||
// Get compilation options
|
||||
var outputName = GetProjectOutput(context.ProjectFile, context.TargetFramework, configuration, outputPath);
|
||||
|
||||
|
@ -311,7 +308,7 @@ namespace Microsoft.DotNet.Tools.Compiler
|
|||
compilerArgs.AddRange(compilationOptions.SerializeToArgs());
|
||||
|
||||
// Add metadata options
|
||||
compilerArgs.AddRange(AssemblyInfoOptions.SerializeToArgs(AssemblyInfoOptions.CreateForProject(context.ProjectFile)));
|
||||
compilerArgs.AddRange(AssemblyInfoOptions.SerializeToArgs(AssemblyInfoOptions.CreateForProject(context)));
|
||||
|
||||
foreach (var dependency in dependencies)
|
||||
{
|
||||
|
@ -825,37 +822,6 @@ namespace Microsoft.DotNet.Tools.Compiler
|
|||
}
|
||||
}
|
||||
|
||||
private static void ShowDependencyInfo(IEnumerable<LibraryExport> dependencies)
|
||||
{
|
||||
if (CommandContext.IsVerbose())
|
||||
{
|
||||
foreach (var dependency in dependencies)
|
||||
{
|
||||
if (!dependency.Library.Resolved)
|
||||
{
|
||||
Reporter.Verbose.WriteLine($" Unable to resolve dependency {dependency.Library.Identity.ToString().Red().Bold()}");
|
||||
Reporter.Verbose.WriteLine("");
|
||||
}
|
||||
else
|
||||
{
|
||||
Reporter.Verbose.WriteLine($" Using {dependency.Library.Identity.Type.Value.Cyan().Bold()} dependency {dependency.Library.Identity.ToString().Cyan().Bold()}");
|
||||
Reporter.Verbose.WriteLine($" Path: {dependency.Library.Path}");
|
||||
|
||||
foreach (var metadataReference in dependency.CompilationAssemblies)
|
||||
{
|
||||
Reporter.Verbose.WriteLine($" Assembly: {metadataReference}");
|
||||
}
|
||||
|
||||
foreach (var sourceReference in dependency.SourceReferences)
|
||||
{
|
||||
Reporter.Verbose.WriteLine($" Source: {sourceReference}");
|
||||
}
|
||||
Reporter.Verbose.WriteLine("");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void CopyFiles(IEnumerable<LibraryAsset> files, string outputPath)
|
||||
{
|
||||
foreach (var file in files)
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
"emitEntryPoint": true
|
||||
},
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.0.0-rc2-23608",
|
||||
"System.Linq": "4.0.1-rc2-23608",
|
||||
"NETStandard.Library": "1.0.0-rc2-23616",
|
||||
"System.Reflection.Metadata": "1.1.0",
|
||||
"Microsoft.DotNet.ProjectModel": "1.0.0-*",
|
||||
"Microsoft.DotNet.Compiler.Common": "1.0.0-*",
|
||||
|
|
|
@ -5,10 +5,7 @@
|
|||
},
|
||||
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.Runtime": "1.0.1-beta-*",
|
||||
"System.IO": "4.0.11-beta-*",
|
||||
"System.Console": "4.0.0-beta-*",
|
||||
"System.Runtime": "4.0.21-beta-*"
|
||||
"NETStandard.Library": "1.0.0-rc2-23616"
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
|
|
|
@ -5,9 +5,7 @@
|
|||
"emitEntryPoint": true
|
||||
},
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.0.0-rc2-23608",
|
||||
|
||||
"System.Linq": "4.0.1-beta-23504",
|
||||
"NETStandard.Library": "1.0.0-rc2-23616",
|
||||
|
||||
"Microsoft.DotNet.ProjectModel": "1.0.0-*",
|
||||
"Microsoft.DotNet.Cli.Utils": {
|
||||
|
|
422
src/Microsoft.DotNet.Tools.Pack/PackageGenerator.cs
Normal file
422
src/Microsoft.DotNet.Tools.Pack/PackageGenerator.cs
Normal file
|
@ -0,0 +1,422 @@
|
|||
// 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;
|
||||
using Microsoft.DotNet.Cli.Utils;
|
||||
using Microsoft.DotNet.ProjectModel;
|
||||
using Microsoft.DotNet.ProjectModel.Files;
|
||||
using Microsoft.DotNet.ProjectModel.Graph;
|
||||
using Microsoft.DotNet.ProjectModel.Utilities;
|
||||
using Microsoft.Extensions.FileSystemGlobbing;
|
||||
using Microsoft.Extensions.FileSystemGlobbing.Abstractions;
|
||||
using NuGet;
|
||||
using NuGet.Frameworks;
|
||||
using NuGet.Packaging.Core;
|
||||
using NuGet.Versioning;
|
||||
using Microsoft.DotNet.Cli.Compiler.Common;
|
||||
|
||||
namespace Microsoft.DotNet.Tools.Compiler
|
||||
{
|
||||
public class PackageGenerator
|
||||
{
|
||||
protected Project Project { get; }
|
||||
|
||||
protected string Configuration { get; }
|
||||
|
||||
protected string OutputPath { get; }
|
||||
|
||||
protected PackageBuilder PackageBuilder { get; private set; }
|
||||
|
||||
public PackageGenerator(Project project, string configuration, string outputPath)
|
||||
{
|
||||
Project = project;
|
||||
Configuration = configuration;
|
||||
OutputPath = outputPath;
|
||||
}
|
||||
|
||||
public bool BuildPackage(IEnumerable<ProjectContext> contexts, List<DiagnosticMessage> packDiagnostics)
|
||||
{
|
||||
|
||||
Reporter.Output.WriteLine($"Producing nuget package \"{GetPackageName()}\" for {Project.Name}");
|
||||
|
||||
PackageBuilder = CreatePackageBuilder(Project);
|
||||
|
||||
// TODO: Report errors for required fields
|
||||
// id
|
||||
// author
|
||||
// description
|
||||
foreach (var context in contexts)
|
||||
{
|
||||
Reporter.Verbose.WriteLine($"Processing {context.TargetFramework.ToString().Yellow()}");
|
||||
ProcessContext(context);
|
||||
Reporter.Verbose.WriteLine("");
|
||||
}
|
||||
|
||||
var packageOutputPath = Path.Combine(GetOutputPath(), GetPackageName() + NuGet.Constants.PackageExtension);
|
||||
|
||||
if (GeneratePackage(packageOutputPath, packDiagnostics))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected virtual void ProcessContext(ProjectContext context)
|
||||
{
|
||||
PopulateDependencies(context);
|
||||
|
||||
var outputPath = GetOutputPath(context);
|
||||
var outputName = GetProjectOutputName(context.TargetFramework);
|
||||
|
||||
var resourceCultures = context.ProjectFile.Files.ResourceFiles
|
||||
.Select(resourceFile => ResourceUtility.GetResourceCultureName(resourceFile.Key))
|
||||
.Distinct();
|
||||
|
||||
foreach (var culture in resourceCultures)
|
||||
{
|
||||
if (string.IsNullOrEmpty(culture))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var resourceFilePath = Path.Combine(culture, $"{Project.Name}.resources.dll");
|
||||
TryAddOutputFile(context, outputPath, resourceFilePath);
|
||||
}
|
||||
|
||||
TryAddOutputFile(context, outputPath, outputName);
|
||||
TryAddOutputFile(context, outputPath, $"{Project.Name}.xml");
|
||||
}
|
||||
|
||||
protected virtual bool GeneratePackage(string nupkg, List<DiagnosticMessage> packDiagnostics)
|
||||
{
|
||||
foreach (var sharedFile in Project.Files.SharedFiles)
|
||||
{
|
||||
var file = new PhysicalPackageFile();
|
||||
file.SourcePath = sharedFile;
|
||||
file.TargetPath = Path.Combine("shared", Path.GetFileName(sharedFile));
|
||||
PackageBuilder.Files.Add(file);
|
||||
}
|
||||
|
||||
if (Project.Files.PackInclude != null && Project.Files.PackInclude.Any())
|
||||
{
|
||||
AddPackageFiles(Project.Files.PackInclude, packDiagnostics);
|
||||
}
|
||||
|
||||
// Write the packages as long as we're still in a success state.
|
||||
if (!packDiagnostics.Any(d => d.Severity == DiagnosticMessageSeverity.Error))
|
||||
{
|
||||
Reporter.Verbose.WriteLine($"Adding package files");
|
||||
foreach (var file in PackageBuilder.Files.OfType<PhysicalPackageFile>())
|
||||
{
|
||||
if (file.SourcePath != null && File.Exists(file.SourcePath))
|
||||
{
|
||||
Reporter.Verbose.WriteLine($"Adding {file.Path.Yellow()}");
|
||||
}
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(nupkg));
|
||||
|
||||
using (var fs = File.Create(nupkg))
|
||||
{
|
||||
PackageBuilder.Save(fs);
|
||||
Reporter.Output.WriteLine($"{Project.Name} -> {Path.GetFullPath(nupkg)}");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void AddPackageFiles(IEnumerable<PackIncludeEntry> packageFiles, IList<DiagnosticMessage> diagnostics)
|
||||
{
|
||||
var rootDirectory = new DirectoryInfoWrapper(new DirectoryInfo(Project.ProjectDirectory));
|
||||
|
||||
foreach (var match in CollectAdditionalFiles(rootDirectory, packageFiles, Project.ProjectFilePath, diagnostics))
|
||||
{
|
||||
PackageBuilder.Files.Add(match);
|
||||
}
|
||||
}
|
||||
|
||||
internal static IEnumerable<PhysicalPackageFile> CollectAdditionalFiles(DirectoryInfoBase rootDirectory, IEnumerable<PackIncludeEntry> projectFileGlobs, string projectFilePath, IList<DiagnosticMessage> diagnostics)
|
||||
{
|
||||
foreach (var entry in projectFileGlobs)
|
||||
{
|
||||
// Evaluate the globs on the right
|
||||
var matcher = new Matcher();
|
||||
matcher.AddIncludePatterns(entry.SourceGlobs);
|
||||
var results = matcher.Execute(rootDirectory);
|
||||
var files = results.Files.ToList();
|
||||
|
||||
// Check for illegal characters
|
||||
if (string.IsNullOrEmpty(entry.Target))
|
||||
{
|
||||
diagnostics.Add(new DiagnosticMessage(
|
||||
ErrorCodes.NU1003,
|
||||
$"Invalid '{ProjectFilesCollection.PackIncludePropertyName}' section. The target '{entry.Target}' is invalid, " +
|
||||
"targets must either be a file name or a directory suffixed with '/'. " +
|
||||
"The root directory of the package can be specified by using a single '/' character.",
|
||||
projectFilePath,
|
||||
DiagnosticMessageSeverity.Error,
|
||||
entry.Line,
|
||||
entry.Column));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entry.Target.Split('/').Any(s => s.Equals(".") || s.Equals("..")))
|
||||
{
|
||||
diagnostics.Add(new DiagnosticMessage(
|
||||
ErrorCodes.NU1004,
|
||||
$"Invalid '{ProjectFilesCollection.PackIncludePropertyName}' section. " +
|
||||
$"The target '{entry.Target}' contains path-traversal characters ('.' or '..'). " +
|
||||
"These characters are not permitted in target paths.",
|
||||
projectFilePath,
|
||||
DiagnosticMessageSeverity.Error,
|
||||
entry.Line,
|
||||
entry.Column));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check the arity of the left
|
||||
if (entry.Target.EndsWith("/"))
|
||||
{
|
||||
var dir = entry.Target.Substring(0, entry.Target.Length - 1).Replace('/', Path.DirectorySeparatorChar);
|
||||
|
||||
foreach (var file in files)
|
||||
{
|
||||
yield return new PhysicalPackageFile()
|
||||
{
|
||||
SourcePath = Path.Combine(rootDirectory.FullName, PathUtility.GetPathWithDirectorySeparator(file.Path)),
|
||||
TargetPath = Path.Combine(dir, PathUtility.GetPathWithDirectorySeparator(file.Stem))
|
||||
};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// It's a file. If the glob matched multiple things, we're sad :(
|
||||
if (files.Count > 1)
|
||||
{
|
||||
// Arity mismatch!
|
||||
string sourceValue = entry.SourceGlobs.Length == 1 ?
|
||||
$"\"{entry.SourceGlobs[0]}\"" :
|
||||
("[" + string.Join(",", entry.SourceGlobs.Select(v => $"\"{v}\"")) + "]");
|
||||
diagnostics.Add(new DiagnosticMessage(
|
||||
ErrorCodes.NU1005,
|
||||
$"Invalid '{ProjectFilesCollection.PackIncludePropertyName}' section. " +
|
||||
$"The target '{entry.Target}' refers to a single file, but the pattern {sourceValue} " +
|
||||
"produces multiple files. To mark the target as a directory, suffix it with '/'.",
|
||||
projectFilePath,
|
||||
DiagnosticMessageSeverity.Error,
|
||||
entry.Line,
|
||||
entry.Column));
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return new PhysicalPackageFile()
|
||||
{
|
||||
SourcePath = Path.Combine(rootDirectory.FullName, files[0].Path),
|
||||
TargetPath = PathUtility.GetPathWithDirectorySeparator(entry.Target)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void TryAddOutputFile(ProjectContext context,
|
||||
string outputPath,
|
||||
string filePath)
|
||||
{
|
||||
var targetPath = Path.Combine("lib", context.TargetFramework.GetTwoDigitShortFolderName(), filePath);
|
||||
var sourcePath = Path.Combine(outputPath, filePath);
|
||||
|
||||
if (!File.Exists(sourcePath))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PackageBuilder.Files.Add(new PhysicalPackageFile
|
||||
{
|
||||
SourcePath = sourcePath,
|
||||
TargetPath = targetPath
|
||||
});
|
||||
}
|
||||
|
||||
private void PopulateDependencies(ProjectContext context)
|
||||
{
|
||||
var dependencies = new List<PackageDependency>();
|
||||
var project = context.RootProject;
|
||||
|
||||
foreach (var dependency in project.Dependencies)
|
||||
{
|
||||
if (!dependency.HasFlag(LibraryDependencyTypeFlag.BecomesNupkgDependency))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: Efficiency
|
||||
var dependencyDescription = context.LibraryManager.GetLibraries().First(l => l.RequestedRanges.Contains(dependency));
|
||||
|
||||
// REVIEW: Can we get this far with unresolved dependencies
|
||||
if (dependencyDescription == null || !dependencyDescription.Resolved)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dependencyDescription.Identity.Type == LibraryType.Project &&
|
||||
((ProjectDescription)dependencyDescription).Project.EmbedInteropTypes)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dependency.Target == LibraryType.ReferenceAssembly)
|
||||
{
|
||||
PackageBuilder.FrameworkAssemblies.Add(new FrameworkAssemblyReference(dependency.Name, new[] { context.TargetFramework }));
|
||||
|
||||
Reporter.Verbose.WriteLine($"Adding framework assembly {dependency.Name.Yellow()}");
|
||||
}
|
||||
else
|
||||
{
|
||||
VersionRange dependencyVersion = null;
|
||||
|
||||
if (dependency.VersionRange == null ||
|
||||
dependency.VersionRange.IsFloating)
|
||||
{
|
||||
dependencyVersion = new VersionRange(dependencyDescription.Identity.Version);
|
||||
}
|
||||
else
|
||||
{
|
||||
dependencyVersion = dependency.VersionRange;
|
||||
}
|
||||
|
||||
Reporter.Verbose.WriteLine($"Adding dependency {dependency.Name.Yellow()} {VersionUtility.RenderVersion(dependencyVersion).Yellow()}");
|
||||
|
||||
dependencies.Add(new PackageDependency(dependency.Name, dependencyVersion));
|
||||
}
|
||||
}
|
||||
|
||||
PackageBuilder.DependencySets.Add(new PackageDependencySet(context.TargetFramework, dependencies));
|
||||
}
|
||||
|
||||
protected virtual string GetPackageName()
|
||||
{
|
||||
return $"{Project.Name}.{Project.Version}";
|
||||
}
|
||||
|
||||
private string GetProjectOutputName(NuGetFramework framework)
|
||||
{
|
||||
var compilationOptions = Project.GetCompilerOptions(framework, Configuration);
|
||||
var outputExtension = ".dll";
|
||||
|
||||
if (framework.IsDesktop() && compilationOptions.EmitEntryPoint.GetValueOrDefault())
|
||||
{
|
||||
outputExtension = ".exe";
|
||||
}
|
||||
|
||||
return Project.Name + outputExtension;
|
||||
}
|
||||
|
||||
protected string GetOutputPath()
|
||||
{
|
||||
var outputPath = string.Empty;
|
||||
|
||||
if (string.IsNullOrEmpty(OutputPath))
|
||||
{
|
||||
outputPath = Path.Combine(
|
||||
GetDefaultRootOutputPath(Project, OutputPath),
|
||||
Cli.Utils.Constants.BinDirectoryName,
|
||||
Configuration);
|
||||
}
|
||||
else
|
||||
{
|
||||
outputPath = OutputPath;
|
||||
}
|
||||
|
||||
return outputPath;
|
||||
}
|
||||
|
||||
protected string GetOutputPath(ProjectContext context)
|
||||
{
|
||||
var outputPath = string.Empty;
|
||||
|
||||
if (string.IsNullOrEmpty(OutputPath))
|
||||
{
|
||||
outputPath = Path.Combine(
|
||||
GetDefaultRootOutputPath(context.ProjectFile, OutputPath),
|
||||
Cli.Utils.Constants.BinDirectoryName,
|
||||
Configuration,
|
||||
context.TargetFramework.GetTwoDigitShortFolderName());
|
||||
}
|
||||
else
|
||||
{
|
||||
outputPath = OutputPath;
|
||||
}
|
||||
|
||||
return outputPath;
|
||||
}
|
||||
|
||||
private static string GetDefaultRootOutputPath(Project project, string outputOptionValue)
|
||||
{
|
||||
string rootOutputPath = string.Empty;
|
||||
|
||||
if (string.IsNullOrEmpty(outputOptionValue))
|
||||
{
|
||||
rootOutputPath = project.ProjectDirectory;
|
||||
}
|
||||
|
||||
return rootOutputPath;
|
||||
}
|
||||
|
||||
private static PackageBuilder CreatePackageBuilder(Project project)
|
||||
{
|
||||
var builder = new PackageBuilder();
|
||||
builder.Authors.AddRange(project.Authors);
|
||||
builder.Owners.AddRange(project.Owners);
|
||||
|
||||
if (builder.Authors.Count == 0)
|
||||
{
|
||||
var defaultAuthor = Environment.GetEnvironmentVariable("NUGET_AUTHOR");
|
||||
if (string.IsNullOrEmpty(defaultAuthor))
|
||||
{
|
||||
builder.Authors.Add(project.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.Authors.Add(defaultAuthor);
|
||||
}
|
||||
}
|
||||
|
||||
builder.Description = project.Description ?? project.Name;
|
||||
builder.Id = project.Name;
|
||||
builder.Version = project.Version;
|
||||
builder.Title = project.Title;
|
||||
builder.Summary = project.Summary;
|
||||
builder.Copyright = project.Copyright;
|
||||
builder.RequireLicenseAcceptance = project.RequireLicenseAcceptance;
|
||||
builder.ReleaseNotes = project.ReleaseNotes;
|
||||
builder.Language = project.Language;
|
||||
builder.Tags.AddRange(project.Tags);
|
||||
|
||||
if (!string.IsNullOrEmpty(project.IconUrl))
|
||||
{
|
||||
builder.IconUrl = new Uri(project.IconUrl);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(project.ProjectUrl))
|
||||
{
|
||||
builder.ProjectUrl = new Uri(project.ProjectUrl);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(project.LicenseUrl))
|
||||
{
|
||||
builder.LicenseUrl = new Uri(project.LicenseUrl);
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -7,17 +7,8 @@ using System.IO;
|
|||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.DotNet.ProjectModel;
|
||||
using NuGet;
|
||||
using Microsoft.Dnx.Runtime.Common.CommandLine;
|
||||
using Microsoft.DotNet.Cli.Utils;
|
||||
using NuGet.Packaging.Core;
|
||||
using Microsoft.DotNet.ProjectModel.Graph;
|
||||
using NuGet.Versioning;
|
||||
using NuGet.Frameworks;
|
||||
using Microsoft.DotNet.ProjectModel.Files;
|
||||
using Microsoft.Extensions.FileSystemGlobbing;
|
||||
using Microsoft.Extensions.FileSystemGlobbing.Abstractions;
|
||||
using Microsoft.DotNet.ProjectModel.Utilities;
|
||||
using Microsoft.DotNet.Cli.Compiler.Common;
|
||||
|
||||
namespace Microsoft.DotNet.Tools.Compiler
|
||||
|
@ -121,392 +112,13 @@ namespace Microsoft.DotNet.Tools.Compiler
|
|||
}
|
||||
}
|
||||
|
||||
Reporter.Output.WriteLine($"Producing nuget package for {project.Name}");
|
||||
|
||||
var packDiagnostics = new List<DiagnosticMessage>();
|
||||
|
||||
// Things compiled now build the package
|
||||
var packageBuilder = CreatePackageBuilder(project);
|
||||
var mainPackageGenerator = new PackageGenerator(project, configuration, outputValue);
|
||||
var symbolsPackageGenerator = new SymbolPackageGenerator(project, configuration, outputValue);
|
||||
|
||||
// TODO: Report errors for required fields
|
||||
// id
|
||||
// author
|
||||
// description
|
||||
foreach (var context in contexts)
|
||||
{
|
||||
Reporter.Verbose.WriteLine($"Processing {context.TargetFramework.ToString().Yellow()}");
|
||||
PopulateDependencies(context, packageBuilder);
|
||||
|
||||
var outputPath = GetOutputPath(context, configuration, outputValue);
|
||||
var outputName = GetProjectOutputName(context.ProjectFile, context.TargetFramework, configuration);
|
||||
|
||||
TryAddOutputFile(packageBuilder, context, outputPath, outputName);
|
||||
|
||||
var resourceCultures = context.ProjectFile.Files.ResourceFiles
|
||||
.Select(resourceFile => ResourceUtility.GetResourceCultureName(resourceFile.Key))
|
||||
.Distinct();
|
||||
|
||||
foreach (var culture in resourceCultures)
|
||||
{
|
||||
if (string.IsNullOrEmpty(culture))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var resourceFilePath = Path.Combine(culture, $"{project.Name}.resources.dll");
|
||||
TryAddOutputFile(packageBuilder, context, outputPath, resourceFilePath);
|
||||
}
|
||||
|
||||
// REVIEW: Do we keep making symbols packages?
|
||||
TryAddOutputFile(packageBuilder, context, outputPath, $"{project.Name}.pdb");
|
||||
TryAddOutputFile(packageBuilder, context, outputPath, $"{project.Name}.mdb");
|
||||
|
||||
TryAddOutputFile(packageBuilder, context, outputPath, $"{project.Name}.xml");
|
||||
|
||||
Reporter.Verbose.WriteLine("");
|
||||
}
|
||||
|
||||
var rootOutputPath = GetOutputPath(project, configuration, outputValue);
|
||||
var packageOutputPath = GetPackagePath(project, rootOutputPath);
|
||||
|
||||
if (GeneratePackage(project, packageBuilder, packageOutputPath, packDiagnostics))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool GeneratePackage(Project project, PackageBuilder packageBuilder, string nupkg, List<DiagnosticMessage> packDiagnostics)
|
||||
{
|
||||
foreach (var sharedFile in project.Files.SharedFiles)
|
||||
{
|
||||
var file = new PhysicalPackageFile();
|
||||
file.SourcePath = sharedFile;
|
||||
file.TargetPath = Path.Combine("shared", Path.GetFileName(sharedFile));
|
||||
packageBuilder.Files.Add(file);
|
||||
}
|
||||
|
||||
var root = project.ProjectDirectory;
|
||||
|
||||
if (project.Files.PackInclude != null && project.Files.PackInclude.Any())
|
||||
{
|
||||
AddPackageFiles(project, project.Files.PackInclude, packageBuilder, packDiagnostics);
|
||||
}
|
||||
|
||||
// Write the packages as long as we're still in a success state.
|
||||
if (!packDiagnostics.Any(d => d.Severity == DiagnosticMessageSeverity.Error))
|
||||
{
|
||||
Reporter.Verbose.WriteLine($"Adding package files");
|
||||
foreach (var file in packageBuilder.Files.OfType<PhysicalPackageFile>())
|
||||
{
|
||||
if (file.SourcePath != null && File.Exists(file.SourcePath))
|
||||
{
|
||||
Reporter.Verbose.WriteLine($"Adding {file.Path.Yellow()}");
|
||||
}
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(nupkg));
|
||||
|
||||
using (var fs = File.Create(nupkg))
|
||||
{
|
||||
packageBuilder.Save(fs);
|
||||
Reporter.Output.WriteLine($"{project.Name} -> {Path.GetFullPath(nupkg)}");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void AddPackageFiles(Project project, IEnumerable<PackIncludeEntry> packageFiles, PackageBuilder packageBuilder, IList<DiagnosticMessage> diagnostics)
|
||||
{
|
||||
var rootDirectory = new DirectoryInfoWrapper(new DirectoryInfo(project.ProjectDirectory));
|
||||
|
||||
foreach (var match in CollectAdditionalFiles(rootDirectory, packageFiles, project.ProjectFilePath, diagnostics))
|
||||
{
|
||||
packageBuilder.Files.Add(match);
|
||||
}
|
||||
}
|
||||
|
||||
internal static IEnumerable<PhysicalPackageFile> CollectAdditionalFiles(DirectoryInfoBase rootDirectory, IEnumerable<PackIncludeEntry> projectFileGlobs, string projectFilePath, IList<DiagnosticMessage> diagnostics)
|
||||
{
|
||||
foreach (var entry in projectFileGlobs)
|
||||
{
|
||||
// Evaluate the globs on the right
|
||||
var matcher = new Matcher();
|
||||
matcher.AddIncludePatterns(entry.SourceGlobs);
|
||||
var results = matcher.Execute(rootDirectory);
|
||||
var files = results.Files.ToList();
|
||||
|
||||
// Check for illegal characters
|
||||
if (string.IsNullOrEmpty(entry.Target))
|
||||
{
|
||||
diagnostics.Add(new DiagnosticMessage(
|
||||
ErrorCodes.NU1003,
|
||||
$"Invalid '{ProjectFilesCollection.PackIncludePropertyName}' section. The target '{entry.Target}' is invalid, " +
|
||||
"targets must either be a file name or a directory suffixed with '/'. " +
|
||||
"The root directory of the package can be specified by using a single '/' character.",
|
||||
projectFilePath,
|
||||
DiagnosticMessageSeverity.Error,
|
||||
entry.Line,
|
||||
entry.Column));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entry.Target.Split('/').Any(s => s.Equals(".") || s.Equals("..")))
|
||||
{
|
||||
diagnostics.Add(new DiagnosticMessage(
|
||||
ErrorCodes.NU1004,
|
||||
$"Invalid '{ProjectFilesCollection.PackIncludePropertyName}' section. " +
|
||||
$"The target '{entry.Target}' contains path-traversal characters ('.' or '..'). " +
|
||||
"These characters are not permitted in target paths.",
|
||||
projectFilePath,
|
||||
DiagnosticMessageSeverity.Error,
|
||||
entry.Line,
|
||||
entry.Column));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check the arity of the left
|
||||
if (entry.Target.EndsWith("/"))
|
||||
{
|
||||
var dir = entry.Target.Substring(0, entry.Target.Length - 1).Replace('/', Path.DirectorySeparatorChar);
|
||||
|
||||
foreach (var file in files)
|
||||
{
|
||||
yield return new PhysicalPackageFile()
|
||||
{
|
||||
SourcePath = Path.Combine(rootDirectory.FullName, PathUtility.GetPathWithDirectorySeparator(file.Path)),
|
||||
TargetPath = Path.Combine(dir, PathUtility.GetPathWithDirectorySeparator(file.Stem))
|
||||
};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// It's a file. If the glob matched multiple things, we're sad :(
|
||||
if (files.Count > 1)
|
||||
{
|
||||
// Arity mismatch!
|
||||
string sourceValue = entry.SourceGlobs.Length == 1 ?
|
||||
$"\"{entry.SourceGlobs[0]}\"" :
|
||||
("[" + string.Join(",", entry.SourceGlobs.Select(v => $"\"{v}\"")) + "]");
|
||||
diagnostics.Add(new DiagnosticMessage(
|
||||
ErrorCodes.NU1005,
|
||||
$"Invalid '{ProjectFilesCollection.PackIncludePropertyName}' section. " +
|
||||
$"The target '{entry.Target}' refers to a single file, but the pattern {sourceValue} " +
|
||||
"produces multiple files. To mark the target as a directory, suffix it with '/'.",
|
||||
projectFilePath,
|
||||
DiagnosticMessageSeverity.Error,
|
||||
entry.Line,
|
||||
entry.Column));
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return new PhysicalPackageFile()
|
||||
{
|
||||
SourcePath = Path.Combine(rootDirectory.FullName, files[0].Path),
|
||||
TargetPath = PathUtility.GetPathWithDirectorySeparator(entry.Target)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void TryAddOutputFile(PackageBuilder packageBuilder,
|
||||
ProjectContext context,
|
||||
string outputPath,
|
||||
string filePath)
|
||||
{
|
||||
var targetPath = Path.Combine("lib", context.TargetFramework.GetTwoDigitShortFolderName(), filePath);
|
||||
var sourcePath = Path.Combine(outputPath, filePath);
|
||||
|
||||
if (!File.Exists(sourcePath))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
packageBuilder.Files.Add(new PhysicalPackageFile
|
||||
{
|
||||
SourcePath = sourcePath,
|
||||
TargetPath = targetPath
|
||||
});
|
||||
}
|
||||
|
||||
public static void PopulateDependencies(ProjectContext context, PackageBuilder packageBuilder)
|
||||
{
|
||||
var dependencies = new List<PackageDependency>();
|
||||
var project = context.RootProject;
|
||||
|
||||
foreach (var dependency in project.Dependencies)
|
||||
{
|
||||
if (!dependency.HasFlag(LibraryDependencyTypeFlag.BecomesNupkgDependency))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: Efficiency
|
||||
var dependencyDescription = context.LibraryManager.GetLibraries().First(l => l.RequestedRanges.Contains(dependency));
|
||||
|
||||
// REVIEW: Can we get this far with unresolved dependencies
|
||||
if (dependencyDescription == null || !dependencyDescription.Resolved)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dependencyDescription.Identity.Type == LibraryType.Project &&
|
||||
((ProjectDescription)dependencyDescription).Project.EmbedInteropTypes)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dependency.Target == LibraryType.ReferenceAssembly)
|
||||
{
|
||||
packageBuilder.FrameworkAssemblies.Add(new FrameworkAssemblyReference(dependency.Name, new[] { context.TargetFramework }));
|
||||
|
||||
Reporter.Verbose.WriteLine($"Adding framework assembly {dependency.Name.Yellow()}");
|
||||
}
|
||||
else
|
||||
{
|
||||
VersionRange dependencyVersion = null;
|
||||
|
||||
if (dependency.VersionRange == null ||
|
||||
dependency.VersionRange.IsFloating)
|
||||
{
|
||||
dependencyVersion = new VersionRange(dependencyDescription.Identity.Version);
|
||||
}
|
||||
else
|
||||
{
|
||||
dependencyVersion = dependency.VersionRange;
|
||||
}
|
||||
|
||||
Reporter.Verbose.WriteLine($"Adding dependency {dependency.Name.Yellow()} {VersionUtility.RenderVersion(dependencyVersion).Yellow()}");
|
||||
|
||||
dependencies.Add(new PackageDependency(dependency.Name, dependencyVersion));
|
||||
}
|
||||
}
|
||||
|
||||
packageBuilder.DependencySets.Add(new PackageDependencySet(context.TargetFramework, dependencies));
|
||||
}
|
||||
|
||||
private static string GetPackagePath(Project project, string outputPath, bool symbols = false)
|
||||
{
|
||||
string fileName = $"{project.Name}.{project.Version}{(symbols ? ".symbols" : string.Empty)}{NuGet.Constants.PackageExtension}";
|
||||
return Path.Combine(outputPath, fileName);
|
||||
}
|
||||
|
||||
private static PackageBuilder CreatePackageBuilder(Project project)
|
||||
{
|
||||
var builder = new PackageBuilder();
|
||||
builder.Authors.AddRange(project.Authors);
|
||||
builder.Owners.AddRange(project.Owners);
|
||||
|
||||
if (builder.Authors.Count == 0)
|
||||
{
|
||||
var defaultAuthor = Environment.GetEnvironmentVariable("NUGET_AUTHOR");
|
||||
if (string.IsNullOrEmpty(defaultAuthor))
|
||||
{
|
||||
builder.Authors.Add(project.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.Authors.Add(defaultAuthor);
|
||||
}
|
||||
}
|
||||
|
||||
builder.Description = project.Description ?? project.Name;
|
||||
builder.Id = project.Name;
|
||||
builder.Version = project.Version;
|
||||
builder.Title = project.Title;
|
||||
builder.Summary = project.Summary;
|
||||
builder.Copyright = project.Copyright;
|
||||
builder.RequireLicenseAcceptance = project.RequireLicenseAcceptance;
|
||||
builder.ReleaseNotes = project.ReleaseNotes;
|
||||
builder.Language = project.Language;
|
||||
builder.Tags.AddRange(project.Tags);
|
||||
|
||||
if (!string.IsNullOrEmpty(project.IconUrl))
|
||||
{
|
||||
builder.IconUrl = new Uri(project.IconUrl);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(project.ProjectUrl))
|
||||
{
|
||||
builder.ProjectUrl = new Uri(project.ProjectUrl);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(project.LicenseUrl))
|
||||
{
|
||||
builder.LicenseUrl = new Uri(project.LicenseUrl);
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
// REVIEW: This code copying kinda sucks
|
||||
private static string GetProjectOutputName(Project project, NuGetFramework framework, string configuration)
|
||||
{
|
||||
var compilationOptions = project.GetCompilerOptions(framework, configuration);
|
||||
var outputExtension = ".dll";
|
||||
|
||||
if (framework.IsDesktop() && compilationOptions.EmitEntryPoint.GetValueOrDefault())
|
||||
{
|
||||
outputExtension = ".exe";
|
||||
}
|
||||
|
||||
return project.Name + outputExtension;
|
||||
}
|
||||
|
||||
private static string GetOutputPath(Project project, string configuration, string outputOptionValue)
|
||||
{
|
||||
var outputPath = string.Empty;
|
||||
|
||||
if (string.IsNullOrEmpty(outputOptionValue))
|
||||
{
|
||||
outputPath = Path.Combine(
|
||||
GetDefaultRootOutputPath(project, outputOptionValue),
|
||||
Cli.Utils.Constants.BinDirectoryName,
|
||||
configuration);
|
||||
}
|
||||
else
|
||||
{
|
||||
outputPath = outputOptionValue;
|
||||
}
|
||||
|
||||
return outputPath;
|
||||
}
|
||||
|
||||
private static string GetOutputPath(ProjectContext context, string configuration, string outputOptionValue)
|
||||
{
|
||||
var outputPath = string.Empty;
|
||||
|
||||
if (string.IsNullOrEmpty(outputOptionValue))
|
||||
{
|
||||
outputPath = Path.Combine(
|
||||
GetDefaultRootOutputPath(context.ProjectFile, outputOptionValue),
|
||||
Cli.Utils.Constants.BinDirectoryName,
|
||||
configuration,
|
||||
context.TargetFramework.GetTwoDigitShortFolderName());
|
||||
}
|
||||
else
|
||||
{
|
||||
outputPath = outputOptionValue;
|
||||
}
|
||||
|
||||
return outputPath;
|
||||
}
|
||||
|
||||
private static string GetDefaultRootOutputPath(Project project, string outputOptionValue)
|
||||
{
|
||||
string rootOutputPath = string.Empty;
|
||||
|
||||
if (string.IsNullOrEmpty(outputOptionValue))
|
||||
{
|
||||
rootOutputPath = project.ProjectDirectory;
|
||||
}
|
||||
|
||||
return rootOutputPath;
|
||||
return mainPackageGenerator.BuildPackage(contexts, packDiagnostics) &&
|
||||
symbolsPackageGenerator.BuildPackage(contexts, packDiagnostics);
|
||||
}
|
||||
}
|
||||
}
|
44
src/Microsoft.DotNet.Tools.Pack/SymbolPackageGenerator.cs
Normal file
44
src/Microsoft.DotNet.Tools.Pack/SymbolPackageGenerator.cs
Normal file
|
@ -0,0 +1,44 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Microsoft.DotNet.ProjectModel;
|
||||
using Microsoft.DotNet.Tools.Common;
|
||||
using NuGet;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Microsoft.DotNet.Tools.Compiler
|
||||
{
|
||||
public class SymbolPackageGenerator: PackageGenerator
|
||||
{
|
||||
public SymbolPackageGenerator(Project project, string configuration, string outputPath) : base(project, configuration, outputPath)
|
||||
{
|
||||
}
|
||||
|
||||
protected override string GetPackageName()
|
||||
{
|
||||
return $"{Project.Name}.{Project.Version}.symbols";
|
||||
}
|
||||
|
||||
protected override void ProcessContext(ProjectContext context)
|
||||
{
|
||||
base.ProcessContext(context);
|
||||
|
||||
var outputPath = GetOutputPath(context);
|
||||
TryAddOutputFile(context, outputPath, $"{Project.Name}.pdb");
|
||||
TryAddOutputFile(context, outputPath, $"{Project.Name}.mdb");
|
||||
}
|
||||
|
||||
protected override bool GeneratePackage(string nupkg, List<DiagnosticMessage> packDiagnostics)
|
||||
{
|
||||
foreach (var path in Project.Files.SourceFiles)
|
||||
{
|
||||
var srcFile = new PhysicalPackageFile();
|
||||
srcFile.SourcePath = path;
|
||||
srcFile.TargetPath = Path.Combine("src", Common.PathUtility.GetRelativePath(Project.ProjectDirectory, path));
|
||||
PackageBuilder.Files.Add(srcFile);
|
||||
}
|
||||
return base.GeneratePackage(nupkg, packDiagnostics);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,9 +5,9 @@
|
|||
"emitEntryPoint": true
|
||||
},
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.0.0-rc2-23608",
|
||||
"System.IO.Compression.ZipFile": "4.0.1-rc2-23608",
|
||||
"System.Linq": "4.0.1-rc2-23608",
|
||||
"NETStandard.Library": "1.0.0-rc2-23616",
|
||||
"System.IO.Compression.ZipFile": "4.0.1-rc2-23616",
|
||||
|
||||
"Microsoft.DotNet.Compiler.Common": "1.0.0-*",
|
||||
"Microsoft.DotNet.ProjectModel": "1.0.0-*",
|
||||
"Microsoft.DotNet.Cli.Utils": {
|
||||
|
@ -24,8 +24,8 @@
|
|||
},
|
||||
"scripts": {
|
||||
"postcompile": [
|
||||
"../../scripts/build/place-binary \"%compile:OutputDir%/%project:Name%.dll\"",
|
||||
"../../scripts/build/place-binary \"%compile:OutputDir%/%project:Name%.pdb\""
|
||||
"../../scripts/build/place-binary \"%compile:OutputDir%/%project:Name%.dll\"",
|
||||
"../../scripts/build/place-binary \"%compile:OutputDir%/%project:Name%.pdb\""
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,11 @@
|
|||
// 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;
|
||||
using Microsoft.Dnx.Runtime.Common.CommandLine;
|
||||
using Microsoft.DotNet.Cli.Utils;
|
||||
using Microsoft.DotNet.ProjectModel;
|
||||
using Microsoft.DotNet.ProjectModel.Compilation;
|
||||
using Microsoft.DotNet.ProjectModel.Graph;
|
||||
using NuGet.Frameworks;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Microsoft.DotNet.Tools.Publish
|
||||
{
|
||||
|
@ -30,58 +25,32 @@ namespace Microsoft.DotNet.Tools.Publish
|
|||
var runtime = app.Option("-r|--runtime <RUNTIME_IDENTIFIER>", "Target runtime to publish for", CommandOptionType.SingleValue);
|
||||
var output = app.Option("-o|--output <OUTPUT_PATH>", "Path in which to publish the app", CommandOptionType.SingleValue);
|
||||
var configuration = app.Option("-c|--configuration <CONFIGURATION>", "Configuration under which to build", CommandOptionType.SingleValue);
|
||||
var project = app.Argument("<PROJECT>", "The project to publish, defaults to the current directory. Can be a path to a project.json or a project directory");
|
||||
var projectPath = app.Argument("<PROJECT>", "The project to publish, defaults to the current directory. Can be a path to a project.json or a project directory");
|
||||
|
||||
app.OnExecute(() =>
|
||||
{
|
||||
NuGetFramework nugetframework = null;
|
||||
var publish = new PublishCommand();
|
||||
|
||||
if (framework.HasValue())
|
||||
publish.Framework = framework.Value();
|
||||
// TODO: Remove default once xplat publish is enabled.
|
||||
publish.Runtime = runtime.Value() ?? RuntimeIdentifier.Current;
|
||||
publish.OutputPath = output.Value();
|
||||
publish.Configuration = configuration.Value() ?? Constants.DefaultConfiguration;
|
||||
|
||||
publish.ProjectPath = projectPath.Value;
|
||||
if (string.IsNullOrEmpty(publish.ProjectPath))
|
||||
{
|
||||
nugetframework = NuGetFramework.Parse(framework.Value());
|
||||
|
||||
if (nugetframework.IsUnsupported)
|
||||
{
|
||||
Reporter.Output.WriteLine($"Unsupported framework {framework.Value()}.".Red());
|
||||
return 1;
|
||||
}
|
||||
publish.ProjectPath = Directory.GetCurrentDirectory();
|
||||
}
|
||||
|
||||
// TODO: Remove this once xplat publish is enabled.
|
||||
if (!runtime.HasValue())
|
||||
if (!publish.TryPrepareForPublish())
|
||||
{
|
||||
runtime.Values.Add(RuntimeIdentifier.Current);
|
||||
}
|
||||
|
||||
// Locate the project and get the name and full path
|
||||
var path = project.Value;
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
path = Directory.GetCurrentDirectory();
|
||||
}
|
||||
|
||||
var projectContexts = ProjectContext.CreateContextForEachTarget(path);
|
||||
projectContexts = GetMatchingProjectContexts(projectContexts, nugetframework, runtime.Value());
|
||||
|
||||
if (projectContexts.Count() == 0)
|
||||
{
|
||||
string errMsg = $"'{project.Value}' cannot be published";
|
||||
if (framework.HasValue() || runtime.HasValue())
|
||||
{
|
||||
errMsg += $" for '{framework.Value()}' '{runtime.Value()}'";
|
||||
}
|
||||
|
||||
Reporter.Output.WriteLine(errMsg.Red());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
foreach (var projectContext in projectContexts)
|
||||
{
|
||||
result += Publish(projectContext, output.Value(), configuration.Value() ?? Constants.DefaultConfiguration);
|
||||
}
|
||||
|
||||
return result;
|
||||
publish.PublishAllProjects();
|
||||
Reporter.Output.WriteLine($"Published {publish.NumberOfPublishedProjects}/{publish.NumberOfProjects} projects successfully");
|
||||
return (publish.NumberOfPublishedProjects == publish.NumberOfProjects) ? 0 : 1;
|
||||
});
|
||||
|
||||
try
|
||||
|
@ -90,151 +59,10 @@ namespace Microsoft.DotNet.Tools.Publish
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
#if DEBUG
|
||||
Console.Error.WriteLine(ex);
|
||||
#else
|
||||
Console.Error.WriteLine(ex.Message);
|
||||
#endif
|
||||
Reporter.Error.WriteLine(ex.Message.Red());
|
||||
Reporter.Verbose.WriteLine(ex.ToString().Yellow());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool CheckArg(CommandOption argument)
|
||||
{
|
||||
if (!argument.HasValue())
|
||||
{
|
||||
Reporter.Error.WriteLine($"Missing required argument: {argument.LongName.Red().Bold()}");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// return the matching framework/runtime ProjectContext.
|
||||
// if 'nugetframework' or 'runtime' is null or empty then it matches with any.
|
||||
private static IEnumerable<ProjectContext> GetMatchingProjectContexts(IEnumerable<ProjectContext> contexts, NuGetFramework framework, string runtimeIdentifier)
|
||||
{
|
||||
var matchingContexts = contexts.Where(context =>
|
||||
{
|
||||
if (context.TargetFramework == null || string.IsNullOrEmpty(context.RuntimeIdentifier))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(runtimeIdentifier) || runtimeIdentifier.Equals(context.RuntimeIdentifier))
|
||||
{
|
||||
if (framework == null || framework.Equals(context.TargetFramework))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
return matchingContexts;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Publish the project for given 'framework (ex - dnxcore50)' and 'runtimeID (ex - win7-x64)'
|
||||
/// </summary>
|
||||
/// <param name="context">project that is to be published</param>
|
||||
/// <param name="outputPath">Location of published files</param>
|
||||
/// <param name="configuration">Debug or Release</param>
|
||||
/// <returns>Return 0 if successful else return non-zero</returns>
|
||||
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()}");
|
||||
|
||||
var options = context.ProjectFile.GetCompilerOptions(context.TargetFramework, configuration);
|
||||
|
||||
// Generate the output path
|
||||
if (string.IsNullOrEmpty(outputPath))
|
||||
{
|
||||
outputPath = Path.Combine(
|
||||
context.ProjectFile.ProjectDirectory,
|
||||
Constants.BinDirectoryName,
|
||||
configuration,
|
||||
context.TargetFramework.GetTwoDigitShortFolderName(),
|
||||
context.RuntimeIdentifier);
|
||||
}
|
||||
|
||||
if (!Directory.Exists(outputPath))
|
||||
{
|
||||
Directory.CreateDirectory(outputPath);
|
||||
}
|
||||
|
||||
// Compile the project (and transitively, all it's dependencies)
|
||||
var result = Command.Create("dotnet-compile",
|
||||
$"--framework \"{context.TargetFramework.DotNetFrameworkName}\" " +
|
||||
$"--output \"{outputPath}\" " +
|
||||
$"--configuration \"{configuration}\" " +
|
||||
"--no-host " +
|
||||
$"\"{context.ProjectFile.ProjectDirectory}\"")
|
||||
.ForwardStdErr()
|
||||
.ForwardStdOut()
|
||||
.Execute();
|
||||
|
||||
if (result.ExitCode != 0)
|
||||
{
|
||||
return result.ExitCode;
|
||||
}
|
||||
|
||||
// Use a library exporter to collect publish assets
|
||||
var exporter = context.CreateExporter(configuration);
|
||||
|
||||
foreach (var export in exporter.GetAllExports())
|
||||
{
|
||||
// Skip copying project references
|
||||
if (export.Library is ProjectDescription)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Reporter.Verbose.WriteLine($"Publishing {export.Library.Identity.ToString().Green().Bold()} ...");
|
||||
|
||||
PublishFiles(export.RuntimeAssemblies, outputPath);
|
||||
PublishFiles(export.NativeLibraries, outputPath);
|
||||
}
|
||||
|
||||
// Publish a host if this is an application
|
||||
if (options.EmitEntryPoint.GetValueOrDefault())
|
||||
{
|
||||
Reporter.Verbose.WriteLine($"Making {context.ProjectFile.Name.Cyan()} runnable ...");
|
||||
PublishHost(context, outputPath);
|
||||
}
|
||||
|
||||
Reporter.Output.WriteLine($"Published to {outputPath}".Green().Bold());
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static int PublishHost(ProjectContext context, string outputPath)
|
||||
{
|
||||
if (context.TargetFramework.IsDesktop())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var hostPath = Path.Combine(AppContext.BaseDirectory, Constants.HostExecutableName);
|
||||
if (!File.Exists(hostPath))
|
||||
{
|
||||
Reporter.Error.WriteLine($"Cannot find {Constants.HostExecutableName} in the dotnet directory.".Red());
|
||||
return 1;
|
||||
}
|
||||
|
||||
var outputExe = Path.Combine(outputPath, context.ProjectFile.Name + Constants.ExeSuffix);
|
||||
|
||||
// Copy the host
|
||||
File.Copy(hostPath, outputExe, overwrite: true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static void PublishFiles(IEnumerable<LibraryAsset> files, string outputPath)
|
||||
{
|
||||
foreach (var file in files)
|
||||
{
|
||||
File.Copy(file.ResolvedPath, Path.Combine(outputPath, Path.GetFileName(file.ResolvedPath)), overwrite: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
195
src/Microsoft.DotNet.Tools.Publish/PublishCommand.cs
Normal file
195
src/Microsoft.DotNet.Tools.Publish/PublishCommand.cs
Normal file
|
@ -0,0 +1,195 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Microsoft.DotNet.Cli.Utils;
|
||||
using Microsoft.DotNet.ProjectModel;
|
||||
using Microsoft.DotNet.ProjectModel.Compilation;
|
||||
using NuGet.Frameworks;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.DotNet.Tools.Publish
|
||||
{
|
||||
public class PublishCommand
|
||||
{
|
||||
public string ProjectPath { get; set; }
|
||||
public string Configuration { get; set; }
|
||||
public string OutputPath { get; set; }
|
||||
public string Framework { get; set; }
|
||||
public string Runtime { get; set; }
|
||||
public NuGetFramework NugetFramework { get; set; }
|
||||
public IEnumerable<ProjectContext> ProjectContexts { get; set; }
|
||||
|
||||
public int NumberOfProjects { get; private set; }
|
||||
public int NumberOfPublishedProjects { get; private set; }
|
||||
|
||||
public bool TryPrepareForPublish()
|
||||
{
|
||||
if (Framework != null)
|
||||
{
|
||||
NugetFramework = NuGetFramework.Parse(Framework);
|
||||
|
||||
if (NugetFramework.IsUnsupported)
|
||||
{
|
||||
Reporter.Output.WriteLine($"Unsupported framework {Framework}.".Red());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ProjectContexts = ProjectContext.CreateContextForEachTarget(ProjectPath);
|
||||
ProjectContexts = GetMatchingProjectContexts(ProjectContexts, NugetFramework, Runtime);
|
||||
|
||||
if (ProjectContexts.Count() == 0)
|
||||
{
|
||||
string errMsg = $"'{ProjectPath}' cannot be published for '{Framework ?? "<no framework provided>"}' '{Runtime ?? "<no runtime provided>"}'";
|
||||
Reporter.Output.WriteLine(errMsg.Red());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void PublishAllProjects()
|
||||
{
|
||||
NumberOfPublishedProjects = 0;
|
||||
NumberOfProjects = 0;
|
||||
foreach (var project in ProjectContexts)
|
||||
{
|
||||
if (PublishProjectContext(project, OutputPath, Configuration))
|
||||
{
|
||||
NumberOfPublishedProjects++;
|
||||
}
|
||||
|
||||
NumberOfProjects++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the matching framework/runtime ProjectContext.
|
||||
/// If 'nugetframework' or 'runtime' is null or empty then it matches with any.
|
||||
/// </summary>
|
||||
private static IEnumerable<ProjectContext> GetMatchingProjectContexts(IEnumerable<ProjectContext> contexts, NuGetFramework framework, string runtimeIdentifier)
|
||||
{
|
||||
foreach (var context in contexts)
|
||||
{
|
||||
if (context.TargetFramework == null || string.IsNullOrEmpty(context.RuntimeIdentifier))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(runtimeIdentifier) || runtimeIdentifier.Equals(context.RuntimeIdentifier))
|
||||
{
|
||||
if (framework == null || framework.Equals(context.TargetFramework))
|
||||
{
|
||||
yield return context;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Publish the project for given 'framework (ex - dnxcore50)' and 'runtimeID (ex - win7-x64)'
|
||||
/// </summary>
|
||||
/// <param name="context">project that is to be published</param>
|
||||
/// <param name="outputPath">Location of published files</param>
|
||||
/// <param name="configuration">Debug or Release</param>
|
||||
/// <returns>Return 0 if successful else return non-zero</returns>
|
||||
private static bool PublishProjectContext(ProjectContext context, string outputPath, string configuration)
|
||||
{
|
||||
Reporter.Output.WriteLine($"Publishing {context.RootProject.Identity.Name.Yellow()} for {context.TargetFramework.DotNetFrameworkName.Yellow()}/{context.RuntimeIdentifier.Yellow()}");
|
||||
|
||||
var options = context.ProjectFile.GetCompilerOptions(context.TargetFramework, configuration);
|
||||
|
||||
// Generate the output path
|
||||
if (string.IsNullOrEmpty(outputPath))
|
||||
{
|
||||
outputPath = Path.Combine(
|
||||
context.ProjectFile.ProjectDirectory,
|
||||
Constants.BinDirectoryName,
|
||||
configuration,
|
||||
context.TargetFramework.GetTwoDigitShortFolderName(),
|
||||
context.RuntimeIdentifier);
|
||||
}
|
||||
|
||||
if (!Directory.Exists(outputPath))
|
||||
{
|
||||
Directory.CreateDirectory(outputPath);
|
||||
}
|
||||
|
||||
// Compile the project (and transitively, all it's dependencies)
|
||||
var result = Command.Create("dotnet-compile",
|
||||
$"--framework \"{context.TargetFramework.DotNetFrameworkName}\" " +
|
||||
$"--output \"{outputPath}\" " +
|
||||
$"--configuration \"{configuration}\" " +
|
||||
"--no-host " +
|
||||
$"\"{context.ProjectFile.ProjectDirectory}\"")
|
||||
.ForwardStdErr()
|
||||
.ForwardStdOut()
|
||||
.Execute();
|
||||
|
||||
if (result.ExitCode != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Use a library exporter to collect publish assets
|
||||
var exporter = context.CreateExporter(configuration);
|
||||
|
||||
foreach (var export in exporter.GetAllExports())
|
||||
{
|
||||
// Skip copying project references
|
||||
if (export.Library is ProjectDescription)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Reporter.Verbose.WriteLine($"Publishing {export.Library.Identity.ToString().Green().Bold()} ...");
|
||||
|
||||
PublishFiles(export.RuntimeAssemblies, outputPath);
|
||||
PublishFiles(export.NativeLibraries, outputPath);
|
||||
}
|
||||
|
||||
// Publish a host if this is an application
|
||||
if (options.EmitEntryPoint.GetValueOrDefault())
|
||||
{
|
||||
Reporter.Verbose.WriteLine($"Making {context.ProjectFile.Name.Cyan()} runnable ...");
|
||||
PublishHost(context, outputPath);
|
||||
}
|
||||
|
||||
Reporter.Output.WriteLine($"Published to {outputPath}".Green().Bold());
|
||||
return true;
|
||||
}
|
||||
|
||||
private static int PublishHost(ProjectContext context, string outputPath)
|
||||
{
|
||||
if (context.TargetFramework.IsDesktop())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var hostPath = Path.Combine(AppContext.BaseDirectory, Constants.HostExecutableName);
|
||||
if (!File.Exists(hostPath))
|
||||
{
|
||||
Reporter.Error.WriteLine($"Cannot find {Constants.HostExecutableName} in the dotnet directory.".Red());
|
||||
return 1;
|
||||
}
|
||||
|
||||
var outputExe = Path.Combine(outputPath, context.ProjectFile.Name + Constants.ExeSuffix);
|
||||
|
||||
// Copy the host
|
||||
File.Copy(hostPath, outputExe, overwrite: true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static void PublishFiles(IEnumerable<LibraryAsset> files, string outputPath)
|
||||
{
|
||||
foreach (var file in files)
|
||||
{
|
||||
File.Copy(file.ResolvedPath, Path.Combine(outputPath, Path.GetFileName(file.ResolvedPath)), overwrite: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,8 +5,7 @@
|
|||
"emitEntryPoint": true
|
||||
},
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.0.0-rc2-23608",
|
||||
"System.Linq": "4.0.1-rc2-23608",
|
||||
"NETStandard.Library": "1.0.0-rc2-23616",
|
||||
|
||||
"Microsoft.DotNet.ProjectModel": "1.0.0-*",
|
||||
"Microsoft.DotNet.Cli.Utils": {
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
"emitEntryPoint": true
|
||||
},
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.0.0-rc2-23608",
|
||||
"System.Linq": "4.0.1-rc2-23608",
|
||||
"NETStandard.Library": "1.0.0-rc2-23616",
|
||||
|
||||
"Microsoft.Net.CSharp.Interactive.netcore": "1.2.0-beta-20151106-02",
|
||||
|
||||
|
|
|
@ -5,9 +5,8 @@
|
|||
"emitEntryPoint": true
|
||||
},
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.0.0-rc2-23608",
|
||||
"System.Linq": "4.0.1-rc2-23608",
|
||||
|
||||
"NETStandard.Library": "1.0.0-rc2-23616",
|
||||
|
||||
"Microsoft.DotNet.ProjectModel": "1.0.0-*",
|
||||
"Microsoft.DotNet.Cli.Utils": {
|
||||
"type": "build",
|
||||
|
|
|
@ -5,10 +5,9 @@
|
|||
"emitEntryPoint": true
|
||||
},
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.0.0-rc2-23608",
|
||||
"System.Linq": "4.0.1-rc2-23608",
|
||||
"System.Xml.XDocument": "4.0.11-rc2-23608",
|
||||
"System.Resources.ReaderWriter": "4.0.0-rc2-23608",
|
||||
"NETStandard.Library": "1.0.0-rc2-23616",
|
||||
"System.Xml.XDocument": "4.0.11-rc2-23616",
|
||||
"System.Resources.ReaderWriter": "4.0.0-rc2-23616",
|
||||
|
||||
"Microsoft.CodeAnalysis.CSharp": "1.1.1",
|
||||
"Microsoft.DotNet.Compiler.Common": "1.0.0-*",
|
||||
|
|
|
@ -5,10 +5,9 @@
|
|||
"emitEntryPoint": true
|
||||
},
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.0.0-rc2-23608",
|
||||
"System.Linq": "4.0.1-beta-23504",
|
||||
"NETStandard.Library": "1.0.0-rc2-23616",
|
||||
|
||||
"Microsoft.Net.Compilers.netcore": "1.2.0-beta-20151117-04",
|
||||
"Microsoft.Net.Compilers.netcore": "1.2.0-beta-20151215-01",
|
||||
"System.CommandLine" : "0.1.0-d111815-3",
|
||||
|
||||
"Microsoft.DotNet.ProjectModel": "1.0.0-*",
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
"emitEntryPoint": true
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.ConsoleHost": "1.0.0-beta-23409",
|
||||
"Microsoft.NETCore.TestHost": "1.0.0-beta-23409",
|
||||
"Microsoft.NETCore.ConsoleHost": "1.0.0-rc2-23616",
|
||||
"Microsoft.NETCore.TestHost": "1.0.0-rc2-23616",
|
||||
"Microsoft.Extensions.Compilation.Abstractions": "1.0.0-*",
|
||||
"Microsoft.DotNet.Cli.Utils": {
|
||||
"type": "build",
|
||||
|
@ -40,11 +40,11 @@
|
|||
"frameworks": {
|
||||
"dnxcore50": {
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.0.0-rc2-23608",
|
||||
"System.Diagnostics.TextWriterTraceListener": "4.0.0-rc2-23608",
|
||||
"System.Diagnostics.TraceSource": "4.0.0-rc2-23608",
|
||||
"System.Dynamic.Runtime": "4.0.11-rc2-23608",
|
||||
"System.Threading.Thread": "4.0.0-rc2-23608"
|
||||
"NETStandard.Library": "1.0.0-rc2-23616",
|
||||
"System.Diagnostics.TextWriterTraceListener": "4.0.0-rc2-23616",
|
||||
"System.Diagnostics.TraceSource": "4.0.0-rc2-23616",
|
||||
"System.Dynamic.Runtime": "4.0.11-rc2-23616",
|
||||
"System.Threading.Thread": "4.0.0-rc2-23616"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -13,13 +13,13 @@
|
|||
"Microsoft.DotNet.ProjectModel": "1.0.0-*",
|
||||
"Microsoft.Extensions.Compilation.Abstractions": "1.0.0-*",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "1.0.0-*",
|
||||
"System.Runtime.Serialization.Primitives": "4.0.11-rc2-23608"
|
||||
"System.Runtime.Serialization.Primitives": "4.0.11-rc2-23616"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnxcore50": {
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.0.0-rc2-23608",
|
||||
"System.Resources.ResourceManager": "4.0.1-rc2-23608"
|
||||
"NETStandard.Library": "1.0.0-rc2-23616",
|
||||
"System.Resources.ResourceManager": "4.0.1-rc2-23616"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -82,7 +82,7 @@ namespace pal
|
|||
typedef std::string string_t;
|
||||
typedef std::stringstream stringstream_t;
|
||||
typedef std::ifstream ifstream_t;
|
||||
typedef long hresult_t;
|
||||
typedef int hresult_t;
|
||||
typedef void* dll_t;
|
||||
typedef void* proc_t;
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ bool pal::find_coreclr(pal::string_t& recv)
|
|||
return true;
|
||||
}
|
||||
|
||||
candidate.assign("/usr/local/share/dotnet/cli/runtime/coreclr");
|
||||
candidate.assign("/usr/local/share/dotnet/runtime/coreclr");
|
||||
if (coreclr_exists_in_dir(candidate)) {
|
||||
recv.assign(candidate);
|
||||
return true;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue