2016-01-29 18:21:37 -08:00
|
|
|
|
// 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 System.Xml.Linq;
|
|
|
|
|
using Microsoft.DotNet.Cli.Compiler.Common;
|
|
|
|
|
using Microsoft.DotNet.Cli.Utils;
|
2016-02-02 10:50:59 -08:00
|
|
|
|
using Microsoft.DotNet.Files;
|
2016-01-29 18:21:37 -08:00
|
|
|
|
using Microsoft.DotNet.ProjectModel;
|
|
|
|
|
using Microsoft.DotNet.ProjectModel.Compilation;
|
|
|
|
|
using Microsoft.DotNet.ProjectModel.Graph;
|
|
|
|
|
using NuGet.Frameworks;
|
|
|
|
|
|
|
|
|
|
namespace Microsoft.Dotnet.Cli.Compiler.Common
|
|
|
|
|
{
|
|
|
|
|
public class Executable
|
|
|
|
|
{
|
|
|
|
|
private readonly ProjectContext _context;
|
|
|
|
|
|
2016-02-03 10:57:25 -08:00
|
|
|
|
private readonly OutputPaths _outputPaths;
|
2016-01-29 18:21:37 -08:00
|
|
|
|
|
2016-02-03 10:57:25 -08:00
|
|
|
|
private readonly LibraryExporter _exporter;
|
|
|
|
|
|
|
|
|
|
public Executable(ProjectContext context, OutputPaths outputPaths, LibraryExporter exporter)
|
2016-01-29 18:21:37 -08:00
|
|
|
|
{
|
|
|
|
|
_context = context;
|
2016-02-03 10:57:25 -08:00
|
|
|
|
_outputPaths = outputPaths;
|
|
|
|
|
_exporter = exporter;
|
2016-01-29 18:21:37 -08:00
|
|
|
|
}
|
|
|
|
|
|
2016-02-03 10:57:25 -08:00
|
|
|
|
public void MakeCompilationOutputRunnable()
|
2016-01-29 18:21:37 -08:00
|
|
|
|
{
|
2016-02-09 10:51:03 -08:00
|
|
|
|
if (string.IsNullOrEmpty(_context.RuntimeIdentifier))
|
|
|
|
|
{
|
|
|
|
|
throw new InvalidOperationException($"Can not make output runnable for framework {_context.TargetFramework}, because it doesn't have runtime target");
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-03 10:57:25 -08:00
|
|
|
|
var outputPath = _outputPaths.RuntimeOutputPath;
|
2016-01-29 18:21:37 -08:00
|
|
|
|
|
|
|
|
|
CopyContentFiles(outputPath);
|
|
|
|
|
|
2016-02-03 10:57:25 -08:00
|
|
|
|
ExportRuntimeAssets(outputPath);
|
2016-01-29 18:21:37 -08:00
|
|
|
|
}
|
|
|
|
|
|
2016-02-03 10:57:25 -08:00
|
|
|
|
private void ExportRuntimeAssets(string outputPath)
|
2016-01-29 18:21:37 -08:00
|
|
|
|
{
|
|
|
|
|
if (_context.TargetFramework.IsDesktop())
|
|
|
|
|
{
|
2016-02-03 10:57:25 -08:00
|
|
|
|
MakeCompilationOutputRunnableForFullFramework(outputPath);
|
2016-01-29 18:21:37 -08:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2016-02-03 10:57:25 -08:00
|
|
|
|
MakeCompilationOutputRunnableForCoreCLR(outputPath);
|
2016-01-29 18:21:37 -08:00
|
|
|
|
}
|
2016-02-03 10:57:25 -08:00
|
|
|
|
}
|
2016-01-29 18:21:37 -08:00
|
|
|
|
|
|
|
|
|
private void MakeCompilationOutputRunnableForFullFramework(
|
2016-02-03 10:57:25 -08:00
|
|
|
|
string outputPath)
|
2016-01-29 18:21:37 -08:00
|
|
|
|
{
|
2016-02-03 10:57:25 -08:00
|
|
|
|
CopyAllDependencies(outputPath, _exporter);
|
|
|
|
|
GenerateBindingRedirects(_exporter);
|
|
|
|
|
}
|
2016-01-29 18:21:37 -08:00
|
|
|
|
|
2016-02-03 10:57:25 -08:00
|
|
|
|
private void MakeCompilationOutputRunnableForCoreCLR(string outputPath)
|
2016-01-29 18:21:37 -08:00
|
|
|
|
{
|
2016-02-03 10:57:25 -08:00
|
|
|
|
WriteDepsFileAndCopyProjectDependencies(_exporter, _context.ProjectFile.Name, outputPath);
|
2016-01-29 18:21:37 -08:00
|
|
|
|
|
|
|
|
|
// TODO: Pick a host based on the RID
|
|
|
|
|
CoreHost.CopyTo(outputPath, _context.ProjectFile.Name + Constants.ExeSuffix);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void CopyContentFiles(string outputPath)
|
|
|
|
|
{
|
|
|
|
|
var contentFiles = new ContentFiles(_context);
|
|
|
|
|
contentFiles.StructuredCopyTo(outputPath);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void CopyAllDependencies(string outputPath, LibraryExporter exporter)
|
|
|
|
|
{
|
|
|
|
|
exporter
|
2016-02-03 10:57:25 -08:00
|
|
|
|
.GetAllExports()
|
2016-01-29 18:21:37 -08:00
|
|
|
|
.SelectMany(e => e.RuntimeAssets())
|
|
|
|
|
.CopyTo(outputPath);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void WriteDepsFileAndCopyProjectDependencies(
|
|
|
|
|
LibraryExporter exporter,
|
|
|
|
|
string projectFileName,
|
|
|
|
|
string outputPath)
|
|
|
|
|
{
|
|
|
|
|
exporter
|
|
|
|
|
.GetDependencies(LibraryType.Package)
|
|
|
|
|
.WriteDepsTo(Path.Combine(outputPath, projectFileName + FileNameSuffixes.Deps));
|
|
|
|
|
|
|
|
|
|
exporter
|
2016-02-03 10:57:25 -08:00
|
|
|
|
.GetAllExports()
|
|
|
|
|
.Where(e => e.Library.Identity.Type == LibraryType.Project)
|
2016-01-29 18:21:37 -08:00
|
|
|
|
.SelectMany(e => e.RuntimeAssets())
|
|
|
|
|
.CopyTo(outputPath);
|
2016-02-03 10:57:25 -08:00
|
|
|
|
}
|
2016-01-29 18:21:37 -08:00
|
|
|
|
|
2016-02-03 10:57:25 -08:00
|
|
|
|
public void GenerateBindingRedirects(LibraryExporter exporter)
|
2016-01-29 18:21:37 -08:00
|
|
|
|
{
|
2016-02-03 10:57:25 -08:00
|
|
|
|
var outputName = _outputPaths.RuntimeFiles.Assembly;
|
2016-01-29 18:21:37 -08:00
|
|
|
|
|
|
|
|
|
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 = outputName + ".config";
|
|
|
|
|
using (var stream = File.Create(path))
|
|
|
|
|
{
|
|
|
|
|
appConfig.Save(stream);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|