ProjectContext.MakeRunnable
PR Feedback Fixing naming of GetContentFiles
This commit is contained in:
parent
a20cffb9e3
commit
ef0fc05119
12 changed files with 374 additions and 219 deletions
|
@ -12,29 +12,29 @@ using System.Text;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using Microsoft.DotNet.ProjectModel.Compilation;
|
using Microsoft.DotNet.ProjectModel.Compilation;
|
||||||
|
|
||||||
namespace Microsoft.DotNet.Tools.Compiler
|
namespace Microsoft.DotNet.Cli.Utils
|
||||||
{
|
{
|
||||||
internal class BindingRedirectGenerator
|
internal static class BindingRedirectGenerator
|
||||||
{
|
{
|
||||||
private const int TokenLength = 8;
|
private const int TokenLength = 8;
|
||||||
private const string Namespace = "urn:schemas-microsoft-com:asm.v1";
|
private const string Namespace = "urn:schemas-microsoft-com:asm.v1";
|
||||||
|
|
||||||
private static XName ConfigurationElementName = XName.Get("configuration");
|
private static readonly XName ConfigurationElementName = XName.Get("configuration");
|
||||||
private static XName RuntimeElementName = XName.Get("runtime");
|
private static readonly XName RuntimeElementName = XName.Get("runtime");
|
||||||
private static XName AssemblyBindingElementName = XName.Get("assemblyBinding", Namespace);
|
private static readonly XName AssemblyBindingElementName = XName.Get("assemblyBinding", Namespace);
|
||||||
private static XName DependentAssemblyElementName = XName.Get("dependentAssembly", Namespace);
|
private static readonly XName DependentAssemblyElementName = XName.Get("dependentAssembly", Namespace);
|
||||||
private static XName AssemblyIdentityElementName = XName.Get("assemblyIdentity", Namespace);
|
private static readonly XName AssemblyIdentityElementName = XName.Get("assemblyIdentity", Namespace);
|
||||||
private static XName BindingRedirectElementName = XName.Get("bindingRedirect", Namespace);
|
private static readonly XName BindingRedirectElementName = XName.Get("bindingRedirect", Namespace);
|
||||||
|
|
||||||
private static XName NameAttributeName = XName.Get("name");
|
private static readonly XName NameAttributeName = XName.Get("name");
|
||||||
private static XName PublicKeyTokenAttributeName = XName.Get("publicKeyToken");
|
private static readonly XName PublicKeyTokenAttributeName = XName.Get("publicKeyToken");
|
||||||
private static XName CultureAttributeName = XName.Get("culture");
|
private static readonly XName CultureAttributeName = XName.Get("culture");
|
||||||
private static XName OldVersionAttributeName = XName.Get("oldVersion");
|
private static readonly XName OldVersionAttributeName = XName.Get("oldVersion");
|
||||||
private static XName NewVersionAttributeName = XName.Get("newVersion");
|
private static readonly XName NewVersionAttributeName = XName.Get("newVersion");
|
||||||
|
|
||||||
private readonly SHA1 _sha1 = SHA1.Create();
|
internal static SHA1 Sha1 { get; } = SHA1.Create();
|
||||||
|
|
||||||
public XDocument Generate(IEnumerable<LibraryExport> dependencies, XDocument document)
|
internal static XDocument GenerateBindingRedirects(this IEnumerable<LibraryExport> dependencies, XDocument document)
|
||||||
{
|
{
|
||||||
var redirects = CollectRedirects(dependencies);
|
var redirects = CollectRedirects(dependencies);
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ namespace Microsoft.DotNet.Tools.Compiler
|
||||||
return document;
|
return document;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddDependentAssembly(AssemblyRedirect redirect, XElement assemblyBindings)
|
private static void AddDependentAssembly(AssemblyRedirect redirect, XElement assemblyBindings)
|
||||||
{
|
{
|
||||||
var dependencyElement = assemblyBindings.Elements(DependentAssemblyElementName)
|
var dependencyElement = assemblyBindings.Elements(DependentAssemblyElementName)
|
||||||
.FirstOrDefault(element => IsSameAssembly(redirect, element));
|
.FirstOrDefault(element => IsSameAssembly(redirect, element));
|
||||||
|
@ -80,16 +80,16 @@ namespace Microsoft.DotNet.Tools.Compiler
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsSameAssembly(AssemblyRedirect redirect, XElement dependentAssemblyElement)
|
private static bool IsSameAssembly(AssemblyRedirect redirect, XElement dependentAssemblyElement)
|
||||||
{
|
{
|
||||||
var identity = dependentAssemblyElement.Element(AssemblyIdentityElementName);
|
var identity = dependentAssemblyElement.Element(AssemblyIdentityElementName);
|
||||||
if (identity == null)
|
if (identity == null)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return (string) identity.Attribute(NameAttributeName) == redirect.From.Name &&
|
return (string)identity.Attribute(NameAttributeName) == redirect.From.Name &&
|
||||||
(string) identity.Attribute(PublicKeyTokenAttributeName) == redirect.From.PublicKeyToken &&
|
(string)identity.Attribute(PublicKeyTokenAttributeName) == redirect.From.PublicKeyToken &&
|
||||||
(string) identity.Attribute(CultureAttributeName) == redirect.From.Culture;
|
(string)identity.Attribute(CultureAttributeName) == redirect.From.Culture;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static XElement GetOrAddElement(XContainer parent, XName elementName)
|
public static XElement GetOrAddElement(XContainer parent, XName elementName)
|
||||||
|
@ -107,7 +107,7 @@ namespace Microsoft.DotNet.Tools.Compiler
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
private AssemblyRedirect[] CollectRedirects(IEnumerable<LibraryExport> dependencies)
|
private static AssemblyRedirect[] CollectRedirects(IEnumerable<LibraryExport> dependencies)
|
||||||
{
|
{
|
||||||
var allRuntimeAssemblies = dependencies.SelectMany(d => d.RuntimeAssemblies).Select(GetAssemblyInfo).ToArray();
|
var allRuntimeAssemblies = dependencies.SelectMany(d => d.RuntimeAssemblies).Select(GetAssemblyInfo).ToArray();
|
||||||
var assemblyLookup = allRuntimeAssemblies.ToDictionary(r => r.Identity.ToLookupKey());
|
var assemblyLookup = allRuntimeAssemblies.ToDictionary(r => r.Identity.ToLookupKey());
|
||||||
|
@ -136,14 +136,14 @@ namespace Microsoft.DotNet.Tools.Compiler
|
||||||
return redirectAssemblies.ToArray();
|
return redirectAssemblies.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private AssemblyReferenceInfo GetAssemblyInfo(LibraryAsset arg)
|
private static AssemblyReferenceInfo GetAssemblyInfo(LibraryAsset arg)
|
||||||
{
|
{
|
||||||
using (var peReader = new PEReader(File.OpenRead(arg.ResolvedPath)))
|
using (var peReader = new PEReader(File.OpenRead(arg.ResolvedPath)))
|
||||||
{
|
{
|
||||||
var metadataReader = peReader.GetMetadataReader();
|
var metadataReader = peReader.GetMetadataReader();
|
||||||
|
|
||||||
var definition = metadataReader.GetAssemblyDefinition();
|
var definition = metadataReader.GetAssemblyDefinition();
|
||||||
|
|
||||||
var identity = new AssemblyIdentity(
|
var identity = new AssemblyIdentity(
|
||||||
metadataReader.GetString(definition.Name),
|
metadataReader.GetString(definition.Name),
|
||||||
definition.Version,
|
definition.Version,
|
||||||
|
@ -168,7 +168,7 @@ namespace Microsoft.DotNet.Tools.Compiler
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetPublicKeyToken(byte[] bytes)
|
private static string GetPublicKeyToken(byte[] bytes)
|
||||||
{
|
{
|
||||||
if (bytes.Length == 0)
|
if (bytes.Length == 0)
|
||||||
{
|
{
|
||||||
|
@ -183,7 +183,7 @@ namespace Microsoft.DotNet.Tools.Compiler
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
token = new byte[TokenLength];
|
token = new byte[TokenLength];
|
||||||
var sha1 = _sha1.ComputeHash(bytes);
|
var sha1 = Sha1.ComputeHash(bytes);
|
||||||
Array.Copy(sha1, sha1.Length - TokenLength, token, 0, TokenLength);
|
Array.Copy(sha1, sha1.Length - TokenLength, token, 0, TokenLength);
|
||||||
Array.Reverse(token);
|
Array.Reverse(token);
|
||||||
}
|
}
|
||||||
|
@ -215,7 +215,7 @@ namespace Microsoft.DotNet.Tools.Compiler
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
Version = version;
|
Version = version;
|
||||||
Culture = string.IsNullOrEmpty(culture)? "neutral" : culture;
|
Culture = string.IsNullOrEmpty(culture) ? "neutral" : culture;
|
||||||
PublicKeyToken = publicKeyToken;
|
PublicKeyToken = publicKeyToken;
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,7 +141,7 @@ namespace Microsoft.DotNet.Cli.Utils
|
||||||
|
|
||||||
return fileNames.Contains(commandName + FileNameSuffixes.DotNet.Exe) &&
|
return fileNames.Contains(commandName + FileNameSuffixes.DotNet.Exe) &&
|
||||||
fileNames.Contains(commandName + FileNameSuffixes.DotNet.DynamicLib) &&
|
fileNames.Contains(commandName + FileNameSuffixes.DotNet.DynamicLib) &&
|
||||||
fileNames.Contains(commandName + FileNameSuffixes.DotNet.Deps);
|
fileNames.Contains(commandName + FileNameSuffixes.Deps);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (commandPackage == null) return null;
|
if (commandPackage == null) return null;
|
||||||
|
|
30
src/Microsoft.DotNet.Cli.Utils/CoreHost.cs
Normal file
30
src/Microsoft.DotNet.Cli.Utils/CoreHost.cs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.DotNet.ProjectModel;
|
||||||
|
|
||||||
|
namespace Microsoft.DotNet.Cli.Utils
|
||||||
|
{
|
||||||
|
internal static class CoreHost
|
||||||
|
{
|
||||||
|
internal static string _path;
|
||||||
|
|
||||||
|
public static string FileName = "corehost" + FileNameSuffixes.CurrentPlatform.Exe;
|
||||||
|
|
||||||
|
public static string Path
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_path == null)
|
||||||
|
{
|
||||||
|
_path = Env.GetCommandPath(FileName, new[] {string.Empty});
|
||||||
|
}
|
||||||
|
|
||||||
|
return _path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CopyTo(string destinationPath)
|
||||||
|
{
|
||||||
|
File.Copy(Path, destinationPath, overwrite: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
src/Microsoft.DotNet.Cli.Utils/CsvFormatter.cs
Normal file
20
src/Microsoft.DotNet.Cli.Utils/CsvFormatter.cs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Microsoft.DotNet.Cli.Utils
|
||||||
|
{
|
||||||
|
internal static class CsvFormatter
|
||||||
|
{
|
||||||
|
internal static string EscapeRow(IEnumerable<string> values)
|
||||||
|
{
|
||||||
|
return values
|
||||||
|
.Select(EscapeValue)
|
||||||
|
.Aggregate((a, v) => a + "," + v);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string EscapeValue(string value)
|
||||||
|
{
|
||||||
|
return "\"" + value.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
61
src/Microsoft.DotNet.Cli.Utils/Env.cs
Normal file
61
src/Microsoft.DotNet.Cli.Utils/Env.cs
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace Microsoft.DotNet.Cli.Utils
|
||||||
|
{
|
||||||
|
internal static class Env
|
||||||
|
{
|
||||||
|
private static IEnumerable<string> _searchPaths;
|
||||||
|
private static IEnumerable<string> _executableExtensions;
|
||||||
|
|
||||||
|
public static IEnumerable<string> ExecutableExtensions
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_executableExtensions == null)
|
||||||
|
{
|
||||||
|
|
||||||
|
_executableExtensions = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
|
||||||
|
? Environment.GetEnvironmentVariable("PATHEXT").Split(';').Select(e => e.ToLower())
|
||||||
|
: new [] { string.Empty };
|
||||||
|
}
|
||||||
|
|
||||||
|
return _executableExtensions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<string> SearchPaths
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_searchPaths == null)
|
||||||
|
{
|
||||||
|
var searchPaths = new List<string> {AppContext.BaseDirectory};
|
||||||
|
|
||||||
|
searchPaths.AddRange(Environment.GetEnvironmentVariable("PATH").Split(Path.PathSeparator));
|
||||||
|
|
||||||
|
_searchPaths = searchPaths;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _searchPaths;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetCommandPath(string commandName, params string[] extensions)
|
||||||
|
{
|
||||||
|
if (!extensions.Any())
|
||||||
|
extensions = Env.ExecutableExtensions.ToArray();
|
||||||
|
|
||||||
|
var commandPath = Env.SearchPaths.Join(
|
||||||
|
extensions,
|
||||||
|
p => true, s => true,
|
||||||
|
(p, s) => Path.Combine(p, commandName + s))
|
||||||
|
.FirstOrDefault(File.Exists);
|
||||||
|
|
||||||
|
return commandPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
59
src/Microsoft.DotNet.Cli.Utils/LibraryExporterExtensions.cs
Normal file
59
src/Microsoft.DotNet.Cli.Utils/LibraryExporterExtensions.cs
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.DotNet.ProjectModel.Compilation;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.DotNet.ProjectModel;
|
||||||
|
|
||||||
|
namespace Microsoft.DotNet.Cli.Utils
|
||||||
|
{
|
||||||
|
internal static class LibraryExporterExtensions
|
||||||
|
{
|
||||||
|
internal static void CopyProjectDependenciesTo(this LibraryExporter exporter, string path, params ProjectDescription[] except)
|
||||||
|
{
|
||||||
|
exporter.GetAllExports()
|
||||||
|
.Where(e => !except.Contains(e.Library))
|
||||||
|
.Where(e => e.Library is ProjectDescription)
|
||||||
|
.SelectMany(e => e.NativeLibraries.Union(e.RuntimeAssemblies))
|
||||||
|
.CopyTo(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void WriteDepsTo(this IEnumerable<LibraryExport> exports, string path)
|
||||||
|
{
|
||||||
|
File.WriteAllLines(path, exports.SelectMany(GenerateLines));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<string> GenerateLines(LibraryExport export)
|
||||||
|
{
|
||||||
|
return GenerateLines(export, export.RuntimeAssemblies, "runtime")
|
||||||
|
.Union(GenerateLines(export, export.NativeLibraries, "native"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<string> GenerateLines(LibraryExport export, IEnumerable<LibraryAsset> items, string type)
|
||||||
|
{
|
||||||
|
return items.Select(i => CsvFormatter.EscapeRow(new[]
|
||||||
|
{
|
||||||
|
export.Library.Identity.Type.Value,
|
||||||
|
export.Library.Identity.Name,
|
||||||
|
export.Library.Identity.Version.ToNormalizedString(),
|
||||||
|
export.Library.Hash,
|
||||||
|
type,
|
||||||
|
i.Name,
|
||||||
|
i.RelativePath
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static IEnumerable<LibraryAsset> RuntimeAssets(this LibraryExport export)
|
||||||
|
{
|
||||||
|
return export.RuntimeAssemblies.Union(export.NativeLibraries);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void CopyTo(this IEnumerable<LibraryAsset> assets, string destinationPath)
|
||||||
|
{
|
||||||
|
foreach (var asset in assets)
|
||||||
|
{
|
||||||
|
File.Copy(asset.ResolvedPath, Path.Combine(destinationPath, Path.GetFileName(asset.ResolvedPath)),
|
||||||
|
overwrite: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Microsoft.DotNet.Tools.Common
|
namespace Microsoft.DotNet.Tools.Common
|
||||||
|
@ -199,5 +198,17 @@ namespace Microsoft.DotNet.Tools.Common
|
||||||
return GetPathWithBackSlashes(path);
|
return GetPathWithBackSlashes(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool HasExtension(string filePath, string extension)
|
||||||
|
{
|
||||||
|
var comparison = StringComparison.Ordinal;
|
||||||
|
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
{
|
||||||
|
comparison = StringComparison.OrdinalIgnoreCase;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Path.GetExtension(filePath).Equals(extension, comparison);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,8 +2,14 @@
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
// 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.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Xml.Linq;
|
||||||
using Microsoft.DotNet.ProjectModel;
|
using Microsoft.DotNet.ProjectModel;
|
||||||
|
using Microsoft.DotNet.ProjectModel.Graph;
|
||||||
|
using Microsoft.DotNet.Tools.Common;
|
||||||
using NuGet.Frameworks;
|
using NuGet.Frameworks;
|
||||||
|
|
||||||
namespace Microsoft.DotNet.Cli.Utils
|
namespace Microsoft.DotNet.Cli.Utils
|
||||||
|
@ -63,5 +69,118 @@ namespace Microsoft.DotNet.Cli.Utils
|
||||||
|
|
||||||
return rootOutputPath;
|
return rootOutputPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static void MakeCompilationOutputRunnable(this ProjectContext context, string outputPath, string configuration)
|
||||||
|
{
|
||||||
|
context
|
||||||
|
.ProjectFile
|
||||||
|
.Files
|
||||||
|
.GetContentFiles()
|
||||||
|
.StructuredCopyTo(context.ProjectDirectory, outputPath)
|
||||||
|
.RemoveAttribute(FileAttributes.ReadOnly);
|
||||||
|
|
||||||
|
var exporter = context.CreateExporter(configuration);
|
||||||
|
|
||||||
|
if (context.TargetFramework.IsDesktop())
|
||||||
|
{
|
||||||
|
exporter
|
||||||
|
.GetDependencies()
|
||||||
|
.SelectMany(e => e.RuntimeAssets())
|
||||||
|
.CopyTo(outputPath);
|
||||||
|
|
||||||
|
GenerateBindingRedirects(context, outputPath, configuration);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
exporter
|
||||||
|
.GetDependencies(LibraryType.Package)
|
||||||
|
.WriteDepsTo(Path.Combine(outputPath, context.ProjectFile.Name + FileNameSuffixes.Deps));
|
||||||
|
|
||||||
|
exporter.GetDependencies(LibraryType.Project)
|
||||||
|
.SelectMany(e => e.RuntimeAssets())
|
||||||
|
.CopyTo(outputPath);
|
||||||
|
|
||||||
|
CoreHost.CopyTo(Path.Combine(outputPath, context.ProjectFile.Name + Constants.ExeSuffix));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<string> StructuredCopyTo(this IEnumerable<string> sourceFiles, string sourceDirectory, string targetDirectory)
|
||||||
|
{
|
||||||
|
if (sourceFiles == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(sourceFiles));
|
||||||
|
}
|
||||||
|
|
||||||
|
var pathMap = sourceFiles
|
||||||
|
.ToDictionary(s => s, s => Path.Combine(
|
||||||
|
targetDirectory,
|
||||||
|
PathUtility.GetRelativePath(sourceDirectory, s)));
|
||||||
|
|
||||||
|
foreach (var targetDir in pathMap.Values
|
||||||
|
.Select(Path.GetDirectoryName)
|
||||||
|
.Distinct()
|
||||||
|
.Where(t => !Directory.Exists(t)))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(targetDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var sourceFilePath in pathMap.Keys)
|
||||||
|
{
|
||||||
|
File.Copy(
|
||||||
|
sourceFilePath,
|
||||||
|
pathMap[sourceFilePath],
|
||||||
|
overwrite: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pathMap.Values;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static IEnumerable<string> RemoveAttribute(this IEnumerable<string> files, FileAttributes attribute)
|
||||||
|
{
|
||||||
|
foreach (var file in files)
|
||||||
|
{
|
||||||
|
var fileAttributes = File.GetAttributes(file);
|
||||||
|
if ((fileAttributes & attribute) == attribute)
|
||||||
|
{
|
||||||
|
File.SetAttributes(file, fileAttributes & ~attribute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void GenerateBindingRedirects(this ProjectContext context, string outputPath, string configuration)
|
||||||
|
{
|
||||||
|
var existingConfig = new DirectoryInfo(context.ProjectDirectory)
|
||||||
|
.EnumerateFiles()
|
||||||
|
.FirstOrDefault(f => f.Name.Equals("app.config", StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
|
XDocument baseAppConfig = null;
|
||||||
|
|
||||||
|
if (existingConfig != null)
|
||||||
|
{
|
||||||
|
using (var fileStream = File.OpenRead(existingConfig.FullName))
|
||||||
|
{
|
||||||
|
baseAppConfig = XDocument.Load(fileStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var appConfig = context.CreateExporter(configuration).GetAllExports().GenerateBindingRedirects(baseAppConfig);
|
||||||
|
|
||||||
|
if (appConfig == null) return;
|
||||||
|
|
||||||
|
var path = Path.Combine(outputPath, context.ProjectFile.Name + ".exe.config");
|
||||||
|
using (var stream = File.Create(path))
|
||||||
|
{
|
||||||
|
appConfig.Save(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetDepsPath(this ProjectContext context, string buildConfiguration)
|
||||||
|
{
|
||||||
|
return Path.Combine(context.GetOutputDirectoryPath(buildConfiguration), context.ProjectFile.Name + ".deps");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
{
|
{
|
||||||
"version": "1.0.0-*",
|
"version": "1.0.0-*",
|
||||||
|
|
||||||
"shared": "**/*.cs",
|
"shared": "**/*.cs",
|
||||||
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"NETStandard.Library": "1.0.0-rc2-23616",
|
"NETStandard.Library": "1.0.0-rc2-23616",
|
||||||
"Microsoft.DotNet.ProjectModel": "1.0.0"
|
"Microsoft.DotNet.ProjectModel": "1.0.0",
|
||||||
},
|
"System.Reflection.Metadata": "1.1.0"
|
||||||
|
},
|
||||||
|
|
||||||
"frameworks": {
|
"frameworks": {
|
||||||
"dnxcore50": { }
|
"dnxcore50": { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,30 @@
|
||||||
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Microsoft.DotNet.ProjectModel
|
namespace Microsoft.DotNet.ProjectModel
|
||||||
{
|
{
|
||||||
public static class FileNameSuffixes
|
public static class FileNameSuffixes
|
||||||
{
|
{
|
||||||
|
public const string Deps = ".deps";
|
||||||
|
|
||||||
|
public static PlatformFileNameSuffixes CurrentPlatform
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return Windows;
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) return Linux;
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) return OSX;
|
||||||
|
|
||||||
|
throw new InvalidOperationException("Unknown Platform");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static PlatformFileNameSuffixes DotNet { get; } = new PlatformFileNameSuffixes
|
public static PlatformFileNameSuffixes DotNet { get; } = new PlatformFileNameSuffixes
|
||||||
{
|
{
|
||||||
DynamicLib = ".dll",
|
DynamicLib = ".dll",
|
||||||
Exe = ".exe",
|
Exe = ".exe",
|
||||||
ProgramDatabase = ".pdb",
|
ProgramDatabase = ".pdb",
|
||||||
StaticLib = ".lib",
|
StaticLib = ".lib"
|
||||||
Deps = ".deps",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public static PlatformFileNameSuffixes Windows { get; } = new PlatformFileNameSuffixes
|
public static PlatformFileNameSuffixes Windows { get; } = new PlatformFileNameSuffixes
|
||||||
|
@ -18,8 +32,7 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
DynamicLib = ".dll",
|
DynamicLib = ".dll",
|
||||||
Exe = ".exe",
|
Exe = ".exe",
|
||||||
ProgramDatabase = ".pdb",
|
ProgramDatabase = ".pdb",
|
||||||
StaticLib = ".lib",
|
StaticLib = ".lib"
|
||||||
Deps = ".deps",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public static PlatformFileNameSuffixes OSX { get; } = new PlatformFileNameSuffixes
|
public static PlatformFileNameSuffixes OSX { get; } = new PlatformFileNameSuffixes
|
||||||
|
@ -27,21 +40,26 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
DynamicLib = ".dylib",
|
DynamicLib = ".dylib",
|
||||||
Exe = "",
|
Exe = "",
|
||||||
ProgramDatabase = ".pdb",
|
ProgramDatabase = ".pdb",
|
||||||
StaticLib = ".a",
|
StaticLib = ".a"
|
||||||
Deps = ".deps"
|
};
|
||||||
|
|
||||||
|
public static PlatformFileNameSuffixes Linux { get; } = new PlatformFileNameSuffixes
|
||||||
|
{
|
||||||
|
DynamicLib = ".so",
|
||||||
|
Exe = "",
|
||||||
|
ProgramDatabase = ".pdb",
|
||||||
|
StaticLib = ".a"
|
||||||
};
|
};
|
||||||
|
|
||||||
public struct PlatformFileNameSuffixes
|
public struct PlatformFileNameSuffixes
|
||||||
{
|
{
|
||||||
public string DynamicLib { get; set; }
|
public string DynamicLib { get; internal set; }
|
||||||
|
|
||||||
public string Exe { get; set; }
|
public string Exe { get; internal set; }
|
||||||
|
|
||||||
public string ProgramDatabase { get; set; }
|
public string ProgramDatabase { get; internal set; }
|
||||||
|
|
||||||
public string StaticLib { get; set; }
|
public string StaticLib { get; internal set; }
|
||||||
|
|
||||||
public string Deps { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,7 +138,7 @@ namespace Microsoft.DotNet.ProjectModel.Files
|
||||||
get { return SharedPatternsGroup.SearchFiles(_projectDirectory).Distinct(); }
|
get { return SharedPatternsGroup.SearchFiles(_projectDirectory).Distinct(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<string> GetCopyToOutputFiles(IEnumerable<string> additionalExcludePatterns = null)
|
public IEnumerable<string> GetContentFiles(IEnumerable<string> additionalExcludePatterns = null)
|
||||||
{
|
{
|
||||||
var patternGroup = new PatternGroup(ContentPatternsGroup.IncludePatterns,
|
var patternGroup = new PatternGroup(ContentPatternsGroup.IncludePatterns,
|
||||||
ContentPatternsGroup.ExcludePatterns.Concat(additionalExcludePatterns ?? new List<string>()),
|
ContentPatternsGroup.ExcludePatterns.Concat(additionalExcludePatterns ?? new List<string>()),
|
||||||
|
|
|
@ -14,6 +14,7 @@ using Microsoft.DotNet.Cli.Compiler.Common;
|
||||||
using Microsoft.DotNet.Tools.Common;
|
using Microsoft.DotNet.Tools.Common;
|
||||||
using Microsoft.DotNet.ProjectModel;
|
using Microsoft.DotNet.ProjectModel;
|
||||||
using Microsoft.DotNet.ProjectModel.Compilation;
|
using Microsoft.DotNet.ProjectModel.Compilation;
|
||||||
|
using Microsoft.DotNet.ProjectModel.Graph;
|
||||||
using Microsoft.DotNet.ProjectModel.Utilities;
|
using Microsoft.DotNet.ProjectModel.Utilities;
|
||||||
using NuGet.Frameworks;
|
using NuGet.Frameworks;
|
||||||
using Microsoft.Extensions.DependencyModel;
|
using Microsoft.Extensions.DependencyModel;
|
||||||
|
@ -348,9 +349,9 @@ namespace Microsoft.DotNet.Tools.Compiler
|
||||||
|
|
||||||
if (success && !args.NoHostValue && compilationOptions.EmitEntryPoint.GetValueOrDefault())
|
if (success && !args.NoHostValue && compilationOptions.EmitEntryPoint.GetValueOrDefault())
|
||||||
{
|
{
|
||||||
MakeRunnable(runtimeContext,
|
var projectContext = ProjectContext.Create(context.ProjectDirectory, context.TargetFramework, new[] { RuntimeIdentifier.Current });
|
||||||
outputPath,
|
projectContext
|
||||||
libraryExporter);
|
.MakeCompilationOutputRunnable(outputPath, args.ConfigValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
return PrintSummary(diagnostics, sw, success);
|
return PrintSummary(diagnostics, sw, success);
|
||||||
|
@ -380,135 +381,13 @@ namespace Microsoft.DotNet.Tools.Compiler
|
||||||
return Path.Combine(outputPath, project.Name + outputExtension);
|
return Path.Combine(outputPath, project.Name + outputExtension);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CleanOrCreateDirectory(string path)
|
|
||||||
{
|
|
||||||
if (Directory.Exists(path))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Directory.Delete(path, recursive: true);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Unable to remove directory: " + path);
|
|
||||||
Console.WriteLine(e.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Directory.CreateDirectory(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void MakeRunnable(ProjectContext runtimeContext, string outputPath, LibraryExporter exporter)
|
|
||||||
{
|
|
||||||
CopyContents(runtimeContext, outputPath);
|
|
||||||
|
|
||||||
if (runtimeContext.TargetFramework.IsDesktop())
|
|
||||||
{
|
|
||||||
// On desktop we need to copy dependencies since we don't own the host
|
|
||||||
foreach (var export in exporter.GetDependencies())
|
|
||||||
{
|
|
||||||
CopyExport(outputPath, export);
|
|
||||||
}
|
|
||||||
|
|
||||||
GenerateBindingRedirects(runtimeContext, outputPath, exporter);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
EmitHost(runtimeContext, outputPath, exporter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void GenerateBindingRedirects(ProjectContext runtimeContext, string outputPath, LibraryExporter exporter)
|
|
||||||
{
|
|
||||||
var appConfigNames = new[] { "app.config", "App.config" };
|
|
||||||
XDocument baseAppConfig = null;
|
|
||||||
|
|
||||||
foreach (var appConfigName in appConfigNames)
|
|
||||||
{
|
|
||||||
var baseAppConfigPath = Path.Combine(runtimeContext.ProjectDirectory, appConfigName);
|
|
||||||
|
|
||||||
if (File.Exists(baseAppConfigPath))
|
|
||||||
{
|
|
||||||
using (var fileStream = File.OpenRead(baseAppConfigPath))
|
|
||||||
{
|
|
||||||
baseAppConfig = XDocument.Load(fileStream);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var generator = new BindingRedirectGenerator();
|
|
||||||
var appConfig = generator.Generate(exporter.GetAllExports(), baseAppConfig);
|
|
||||||
|
|
||||||
if (appConfig != null)
|
|
||||||
{
|
|
||||||
var path = Path.Combine(outputPath, runtimeContext.ProjectFile.Name + ".exe.config");
|
|
||||||
using (var stream = File.Create(path))
|
|
||||||
{
|
|
||||||
appConfig.Save(stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void CopyExport(string outputPath, LibraryExport export)
|
private static void CopyExport(string outputPath, LibraryExport export)
|
||||||
{
|
{
|
||||||
CopyFiles(export.RuntimeAssemblies, outputPath);
|
CopyFiles(export.RuntimeAssemblies, outputPath);
|
||||||
CopyFiles(export.NativeLibraries, outputPath);
|
CopyFiles(export.NativeLibraries, outputPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitHost(ProjectContext runtimeContext, string outputPath, LibraryExporter exporter)
|
|
||||||
{
|
|
||||||
// Write the Host information file (basically a simplified form of the lock file)
|
|
||||||
var lines = new List<string>();
|
|
||||||
foreach (var export in exporter.GetAllExports())
|
|
||||||
{
|
|
||||||
if (export.Library == runtimeContext.RootProject)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (export.Library is ProjectDescription)
|
|
||||||
{
|
|
||||||
// Copy project dependencies to the output folder
|
|
||||||
CopyFiles(export.RuntimeAssemblies, outputPath);
|
|
||||||
CopyFiles(export.NativeLibraries, outputPath);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lines.AddRange(GenerateLines(export, export.RuntimeAssemblies, "runtime"));
|
|
||||||
lines.AddRange(GenerateLines(export, export.NativeLibraries, "native"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
File.WriteAllLines(Path.Combine(outputPath, runtimeContext.ProjectFile.Name + ".deps"), lines);
|
|
||||||
|
|
||||||
// Copy the host in
|
|
||||||
CopyHost(Path.Combine(outputPath, runtimeContext.ProjectFile.Name + Constants.ExeSuffix));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void CopyHost(string target)
|
|
||||||
{
|
|
||||||
var hostPath = Path.Combine(AppContext.BaseDirectory, Constants.HostExecutableName);
|
|
||||||
File.Copy(hostPath, target, overwrite: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IEnumerable<string> GenerateLines(LibraryExport export, IEnumerable<LibraryAsset> items, string type)
|
|
||||||
{
|
|
||||||
return items.Select(item =>
|
|
||||||
EscapeCsv(export.Library.Identity.Type.Value) + "," +
|
|
||||||
EscapeCsv(export.Library.Identity.Name) + "," +
|
|
||||||
EscapeCsv(export.Library.Identity.Version.ToNormalizedString()) + "," +
|
|
||||||
EscapeCsv(export.Library.Hash) + "," +
|
|
||||||
EscapeCsv(type) + "," +
|
|
||||||
EscapeCsv(item.Name) + "," +
|
|
||||||
EscapeCsv(item.RelativePath) + ",");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string EscapeCsv(string input)
|
|
||||||
{
|
|
||||||
return "\"" + input.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool PrintSummary(List<DiagnosticMessage> diagnostics, Stopwatch sw, bool success = true)
|
private static bool PrintSummary(List<DiagnosticMessage> diagnostics, Stopwatch sw, bool success = true)
|
||||||
{
|
{
|
||||||
PrintDiagnostics(diagnostics);
|
PrintDiagnostics(diagnostics);
|
||||||
|
@ -663,49 +542,6 @@ namespace Microsoft.DotNet.Tools.Compiler
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CopyContents(ProjectContext context, string outputPath)
|
|
||||||
{
|
|
||||||
var sourceFiles = context.ProjectFile.Files.GetCopyToOutputFiles();
|
|
||||||
Copy(sourceFiles, context.ProjectDirectory, outputPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void Copy(IEnumerable<string> sourceFiles, string sourceDirectory, string targetDirectory)
|
|
||||||
{
|
|
||||||
if (sourceFiles == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(sourceFiles));
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceDirectory = EnsureTrailingSlash(sourceDirectory);
|
|
||||||
targetDirectory = EnsureTrailingSlash(targetDirectory);
|
|
||||||
|
|
||||||
foreach (var sourceFilePath in sourceFiles)
|
|
||||||
{
|
|
||||||
var fileName = Path.GetFileName(sourceFilePath);
|
|
||||||
|
|
||||||
var targetFilePath = sourceFilePath.Replace(sourceDirectory, targetDirectory);
|
|
||||||
var targetFileParentFolder = Path.GetDirectoryName(targetFilePath);
|
|
||||||
|
|
||||||
// Create directory before copying a file
|
|
||||||
if (!Directory.Exists(targetFileParentFolder))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(targetFileParentFolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
File.Copy(
|
|
||||||
sourceFilePath,
|
|
||||||
targetFilePath,
|
|
||||||
overwrite: true);
|
|
||||||
|
|
||||||
// clear read-only bit if set
|
|
||||||
var fileAttributes = File.GetAttributes(targetFilePath);
|
|
||||||
if ((fileAttributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
|
|
||||||
{
|
|
||||||
File.SetAttributes(targetFilePath, fileAttributes & ~FileAttributes.ReadOnly);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string EnsureTrailingSlash(string path)
|
private static string EnsureTrailingSlash(string path)
|
||||||
{
|
{
|
||||||
return EnsureTrailingCharacter(path, Path.DirectorySeparatorChar);
|
return EnsureTrailingCharacter(path, Path.DirectorySeparatorChar);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue