Merge pull request #699 from piotrpMSFT/piotrpMSFT/issue696/DepsGen

ProjectContext.MakeRunnable
This commit is contained in:
Piotr Puszkiewicz 2016-01-05 11:46:52 -08:00
commit 615f5ac787
22 changed files with 477 additions and 307 deletions

View file

@ -141,7 +141,7 @@ namespace Microsoft.DotNet.Cli.Utils
return fileNames.Contains(commandName + FileNameSuffixes.DotNet.Exe) &&
fileNames.Contains(commandName + FileNameSuffixes.DotNet.DynamicLib) &&
fileNames.Contains(commandName + FileNameSuffixes.DotNet.Deps);
fileNames.Contains(commandName + FileNameSuffixes.Deps);
});
if (commandPackage == null) return null;

View file

@ -1,8 +1,6 @@
// 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.IO;
namespace Microsoft.DotNet.Cli.Utils
{
public struct CommandResult

View file

@ -0,0 +1,63 @@
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;
}
}
}

View file

@ -3,7 +3,6 @@
using System;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
namespace Microsoft.DotNet.Tools.Common
@ -199,5 +198,17 @@ namespace Microsoft.DotNet.Tools.Common
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);
}
}
}

View file

@ -1,67 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.IO;
using Microsoft.DotNet.ProjectModel;
using NuGet.Frameworks;
namespace Microsoft.DotNet.Cli.Utils
{
internal static class ProjectContextExtensions
{
public static string ProjectName(this ProjectContext context) => context.RootProject.Identity.Name;
public static string GetOutputPath(this ProjectContext context, string configuration, string currentOutputPath)
{
var outputPath = string.Empty;
if (string.IsNullOrEmpty(currentOutputPath))
{
outputPath = Path.Combine(
GetDefaultRootOutputPath(context, currentOutputPath),
Constants.BinDirectoryName,
configuration,
context.TargetFramework.GetTwoDigitShortFolderName());
}
else
{
outputPath = currentOutputPath;
}
return outputPath;
}
public static string GetIntermediateOutputPath(this ProjectContext context, string configuration, string intermediateOutputValue, string currentOutputPath)
{
var intermediateOutputPath = string.Empty;
if (string.IsNullOrEmpty(intermediateOutputValue))
{
intermediateOutputPath = Path.Combine(
GetDefaultRootOutputPath(context, currentOutputPath),
Constants.ObjDirectoryName,
configuration,
context.TargetFramework.GetTwoDigitShortFolderName());
}
else
{
intermediateOutputPath = intermediateOutputValue;
}
return intermediateOutputPath;
}
public static string GetDefaultRootOutputPath(ProjectContext context, string currentOutputPath)
{
string rootOutputPath = string.Empty;
if (string.IsNullOrEmpty(currentOutputPath))
{
rootOutputPath = context.ProjectFile.ProjectDirectory;
}
return rootOutputPath;
}
}
}

View file

@ -1,14 +1,15 @@
{
"version": "1.0.0-*",
"version": "1.0.0-*",
"shared": "**/*.cs",
"shared": "**/*.cs",
"dependencies": {
"NETStandard.Library": "1.0.0-rc2-23616",
"Microsoft.DotNet.ProjectModel": "1.0.0"
},
"dependencies": {
"NETStandard.Library": "1.0.0-rc2-23616",
"Microsoft.DotNet.ProjectModel": "1.0.0",
"System.Reflection.Metadata": "1.1.0"
},
"frameworks": {
"dnxcore50": { }
}
"frameworks": {
"dnxcore50": { }
}
}

View file

@ -11,7 +11,7 @@ using System.IO;
using System.Runtime.Versioning;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Microsoft.Dotnet.Cli.Compiler.Common
namespace Microsoft.DotNet.Cli.Compiler.Common
{
public class AssemblyInfoFileGenerator
{

View file

@ -2,13 +2,11 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
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
namespace Microsoft.DotNet.Cli.Compiler.Common
{
public class AssemblyInfoOptions
{

View file

@ -12,29 +12,29 @@ using System.Text;
using System.Xml.Linq;
using Microsoft.DotNet.ProjectModel.Compilation;
namespace Microsoft.DotNet.Tools.Compiler
namespace Microsoft.DotNet.Cli.Compiler.Common
{
internal class BindingRedirectGenerator
public static class BindingRedirectGenerator
{
private const int TokenLength = 8;
private const string Namespace = "urn:schemas-microsoft-com:asm.v1";
private static XName ConfigurationElementName = XName.Get("configuration");
private static XName RuntimeElementName = XName.Get("runtime");
private static XName AssemblyBindingElementName = XName.Get("assemblyBinding", Namespace);
private static XName DependentAssemblyElementName = XName.Get("dependentAssembly", Namespace);
private static XName AssemblyIdentityElementName = XName.Get("assemblyIdentity", Namespace);
private static XName BindingRedirectElementName = XName.Get("bindingRedirect", Namespace);
private static readonly XName ConfigurationElementName = XName.Get("configuration");
private static readonly XName RuntimeElementName = XName.Get("runtime");
private static readonly XName AssemblyBindingElementName = XName.Get("assemblyBinding", Namespace);
private static readonly XName DependentAssemblyElementName = XName.Get("dependentAssembly", Namespace);
private static readonly XName AssemblyIdentityElementName = XName.Get("assemblyIdentity", Namespace);
private static readonly XName BindingRedirectElementName = XName.Get("bindingRedirect", Namespace);
private static XName NameAttributeName = XName.Get("name");
private static XName PublicKeyTokenAttributeName = XName.Get("publicKeyToken");
private static XName CultureAttributeName = XName.Get("culture");
private static XName OldVersionAttributeName = XName.Get("oldVersion");
private static XName NewVersionAttributeName = XName.Get("newVersion");
private static readonly XName NameAttributeName = XName.Get("name");
private static readonly XName PublicKeyTokenAttributeName = XName.Get("publicKeyToken");
private static readonly XName CultureAttributeName = XName.Get("culture");
private static readonly XName OldVersionAttributeName = XName.Get("oldVersion");
private static readonly XName NewVersionAttributeName = XName.Get("newVersion");
private readonly SHA1 _sha1 = SHA1.Create();
private 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);
@ -57,7 +57,7 @@ namespace Microsoft.DotNet.Tools.Compiler
return document;
}
private void AddDependentAssembly(AssemblyRedirect redirect, XElement assemblyBindings)
private static void AddDependentAssembly(AssemblyRedirect redirect, XElement assemblyBindings)
{
var dependencyElement = assemblyBindings.Elements(DependentAssemblyElementName)
.FirstOrDefault(element => IsSameAssembly(redirect, element));
@ -80,19 +80,19 @@ 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);
if (identity == null)
{
return false;
}
return (string) identity.Attribute(NameAttributeName) == redirect.From.Name &&
(string) identity.Attribute(PublicKeyTokenAttributeName) == redirect.From.PublicKeyToken &&
(string) identity.Attribute(CultureAttributeName) == redirect.From.Culture;
return (string)identity.Attribute(NameAttributeName) == redirect.From.Name &&
(string)identity.Attribute(PublicKeyTokenAttributeName) == redirect.From.PublicKeyToken &&
(string)identity.Attribute(CultureAttributeName) == redirect.From.Culture;
}
public static XElement GetOrAddElement(XContainer parent, XName elementName)
private static XElement GetOrAddElement(XContainer parent, XName elementName)
{
XElement element;
if (parent.Element(elementName) != null)
@ -107,7 +107,7 @@ namespace Microsoft.DotNet.Tools.Compiler
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 assemblyLookup = allRuntimeAssemblies.ToDictionary(r => r.Identity.ToLookupKey());
@ -136,14 +136,14 @@ namespace Microsoft.DotNet.Tools.Compiler
return redirectAssemblies.ToArray();
}
private AssemblyReferenceInfo GetAssemblyInfo(LibraryAsset arg)
private static AssemblyReferenceInfo GetAssemblyInfo(LibraryAsset arg)
{
using (var peReader = new PEReader(File.OpenRead(arg.ResolvedPath)))
{
var metadataReader = peReader.GetMetadataReader();
var definition = metadataReader.GetAssemblyDefinition();
var identity = new AssemblyIdentity(
metadataReader.GetString(definition.Name),
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)
{
@ -183,7 +183,7 @@ namespace Microsoft.DotNet.Tools.Compiler
else
{
token = new byte[TokenLength];
var sha1 = _sha1.ComputeHash(bytes);
var sha1 = Sha1.ComputeHash(bytes);
Array.Copy(sha1, sha1.Length - TokenLength, token, 0, TokenLength);
Array.Reverse(token);
}
@ -215,7 +215,7 @@ namespace Microsoft.DotNet.Tools.Compiler
{
Name = name;
Version = version;
Culture = string.IsNullOrEmpty(culture)? "neutral" : culture;
Culture = string.IsNullOrEmpty(culture) ? "neutral" : culture;
PublicKeyToken = publicKeyToken;
}

View file

@ -0,0 +1,31 @@
using System.IO;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.ProjectModel;
namespace Microsoft.DotNet.Cli.Compiler.Common
{
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);
}
}
}

View file

@ -0,0 +1,20 @@
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.DotNet.Cli.Compiler.Common
{
internal static class DepsFormatter
{
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("\"", "\\\"") + "\"";
}
}
}

View file

@ -0,0 +1,59 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.DotNet.ProjectModel;
using Microsoft.DotNet.ProjectModel.Compilation;
namespace Microsoft.DotNet.Cli.Compiler.Common
{
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 => DepsFormatter.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);
}
}
}
}

View file

@ -0,0 +1,211 @@
// 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 System.Xml.Linq;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.ProjectModel;
using Microsoft.DotNet.ProjectModel.Compilation;
using Microsoft.DotNet.ProjectModel.Graph;
using Microsoft.DotNet.Tools.Common;
using NuGet.Frameworks;
namespace Microsoft.DotNet.Cli.Compiler.Common
{
public static class ProjectContextExtensions
{
public static string ProjectName(this ProjectContext context) => context.RootProject.Identity.Name;
public static string GetOutputPath(this ProjectContext context, string configuration, string currentOutputPath)
{
var outputPath = string.Empty;
if (string.IsNullOrEmpty(currentOutputPath))
{
outputPath = Path.Combine(
GetDefaultRootOutputPath(context, currentOutputPath),
Constants.BinDirectoryName,
configuration,
context.TargetFramework.GetTwoDigitShortFolderName());
}
else
{
outputPath = currentOutputPath;
}
return outputPath;
}
public static string GetIntermediateOutputPath(this ProjectContext context, string configuration, string intermediateOutputValue, string currentOutputPath)
{
var intermediateOutputPath = string.Empty;
if (string.IsNullOrEmpty(intermediateOutputValue))
{
intermediateOutputPath = Path.Combine(
GetDefaultRootOutputPath(context, currentOutputPath),
Constants.ObjDirectoryName,
configuration,
context.TargetFramework.GetTwoDigitShortFolderName());
}
else
{
intermediateOutputPath = intermediateOutputValue;
}
return intermediateOutputPath;
}
public static string GetDefaultRootOutputPath(ProjectContext context, string currentOutputPath)
{
var rootOutputPath = string.Empty;
if (string.IsNullOrEmpty(currentOutputPath))
{
rootOutputPath = context.ProjectFile.ProjectDirectory;
}
return rootOutputPath;
}
public 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, exporter, outputPath);
}
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));
}
sourceDirectory = EnsureTrailingSlash(sourceDirectory);
targetDirectory = EnsureTrailingSlash(targetDirectory);
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 string EnsureTrailingSlash(string path)
{
return EnsureTrailingCharacter(path, Path.DirectorySeparatorChar);
}
private static string EnsureTrailingCharacter(string path, char trailingCharacter)
{
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
// if the path is empty, we want to return the original string instead of a single trailing character.
if (path.Length == 0 || path[path.Length - 1] == trailingCharacter)
{
return path;
}
return path + trailingCharacter;
}
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, LibraryExporter exporter, string outputPath)
{
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 = exporter.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");
}
}
}

View file

@ -14,7 +14,7 @@
"Microsoft.DotNet.Cli.Utils": {
"type": "build",
"version": "1.0.0-*"
},
}
},
"frameworks": {
"dnxcore50": { }

View file

@ -1,16 +1,30 @@
using System;
using System.Runtime.InteropServices;
namespace Microsoft.DotNet.ProjectModel
{
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
{
DynamicLib = ".dll",
Exe = ".exe",
ProgramDatabase = ".pdb",
StaticLib = ".lib",
Deps = ".deps",
StaticLib = ".lib"
};
public static PlatformFileNameSuffixes Windows { get; } = new PlatformFileNameSuffixes
@ -18,8 +32,7 @@ namespace Microsoft.DotNet.ProjectModel
DynamicLib = ".dll",
Exe = ".exe",
ProgramDatabase = ".pdb",
StaticLib = ".lib",
Deps = ".deps",
StaticLib = ".lib"
};
public static PlatformFileNameSuffixes OSX { get; } = new PlatformFileNameSuffixes
@ -27,21 +40,26 @@ namespace Microsoft.DotNet.ProjectModel
DynamicLib = ".dylib",
Exe = "",
ProgramDatabase = ".pdb",
StaticLib = ".a",
Deps = ".deps"
StaticLib = ".a"
};
public static PlatformFileNameSuffixes Linux { get; } = new PlatformFileNameSuffixes
{
DynamicLib = ".so",
Exe = "",
ProgramDatabase = ".pdb",
StaticLib = ".a"
};
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 Deps { get; set; }
public string StaticLib { get; internal set; }
}
}
}

View file

@ -138,7 +138,7 @@ namespace Microsoft.DotNet.ProjectModel.Files
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,
ContentPatternsGroup.ExcludePatterns.Concat(additionalExcludePatterns ?? new List<string>()),

View file

@ -10,7 +10,7 @@ using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.ProjectModel;
using Microsoft.DotNet.Tools.Compiler;
using Microsoft.DotNet.ProjectModel.Utilities;
using Microsoft.DotNet.Cli.Compiler.Common;
namespace Microsoft.DotNet.Tools.Build
{

View file

@ -4,7 +4,6 @@
using System;
using System.CommandLine;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
@ -13,7 +12,6 @@ using System.Text;
using Microsoft.DotNet.Cli.Compiler.Common;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.ProjectModel;
using Microsoft.Dotnet.Cli.Compiler.Common;
namespace Microsoft.DotNet.Tools.Compiler.Csc
{

View file

@ -4,7 +4,6 @@
using System;
using System.CommandLine;
using System.Collections.Generic;
using System.Reflection;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
@ -13,7 +12,6 @@ using System.Text;
using Microsoft.DotNet.Cli.Compiler.Common;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.ProjectModel;
using Microsoft.Dotnet.Cli.Compiler.Common;
namespace Microsoft.DotNet.Tools.Compiler.Fsc
{

View file

@ -6,12 +6,8 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using Microsoft.Dnx.Runtime.Common.CommandLine;
using Microsoft.Dotnet.Cli.Compiler.Common;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Cli.Compiler.Common;
using Microsoft.DotNet.Tools.Common;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.ProjectModel;
using Microsoft.DotNet.ProjectModel.Compilation;
using Microsoft.DotNet.ProjectModel.Utilities;
@ -348,9 +344,9 @@ namespace Microsoft.DotNet.Tools.Compiler
if (success && !args.NoHostValue && compilationOptions.EmitEntryPoint.GetValueOrDefault())
{
MakeRunnable(runtimeContext,
outputPath,
libraryExporter);
var projectContext = ProjectContext.Create(context.ProjectDirectory, context.TargetFramework, new[] { RuntimeIdentifier.Current });
projectContext
.MakeCompilationOutputRunnable(outputPath, args.ConfigValue);
}
return PrintSummary(diagnostics, sw, success);
@ -380,135 +376,13 @@ namespace Microsoft.DotNet.Tools.Compiler
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)
{
CopyFiles(export.RuntimeAssemblies, 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)
{
PrintDiagnostics(diagnostics);
@ -663,49 +537,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)
{
return EnsureTrailingCharacter(path, Path.DirectorySeparatorChar);

View file

@ -1,12 +1,12 @@
// 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.IO;
using System.Linq;
using Microsoft.Dnx.Runtime.Common.CommandLine;
using Microsoft.DotNet.Cli.Compiler.Common;
using Microsoft.DotNet.Cli.Utils;
using System;
using Microsoft.Dotnet.Cli.Compiler.Common;
namespace Microsoft.DotNet.Tools.Resgen
{

View file

@ -7,7 +7,7 @@ using System.IO;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.Dotnet.Cli.Compiler.Common;
using Microsoft.DotNet.Cli.Compiler.Common;
using Microsoft.DotNet.Cli.Utils;
namespace Microsoft.DotNet.Tools.Resgen