Merge pull request #1809 from dotnet/anurse/publish-layout
Add support for portable application layout
This commit is contained in:
commit
5b0afe7880
38 changed files with 371 additions and 192 deletions
|
@ -1,3 +0,0 @@
|
||||||
public static class Thingy
|
|
||||||
{
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
public static class Thingy
|
|
||||||
{
|
|
||||||
}
|
|
12
TestAssets/TestProjects/PortableTests/PortableApp/Program.cs
Normal file
12
TestAssets/TestProjects/PortableTests/PortableApp/Program.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace PortableApp
|
||||||
|
{
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Hello, World!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,14 +1,17 @@
|
||||||
{
|
{
|
||||||
|
"compilationOptions": {
|
||||||
|
"emitEntryPoint": true
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
},
|
},
|
||||||
"frameworks": {
|
"frameworks": {
|
||||||
"netstandardapp1.5": {
|
"netstandard1.5": {
|
||||||
"imports": [
|
"imports": [
|
||||||
"dnxcore50",
|
"dnxcore50",
|
||||||
"portable-net45+win8"
|
"portable-net45+win8"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"NETStandard.Library": "1.0.0-rc2-23901"
|
"Microsoft.NETCore.App": "1.0.0-rc2-23911"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace PortableAppWithNative
|
||||||
|
{
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Hello, World!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"compilationOptions": {
|
||||||
|
"emitEntryPoint": true
|
||||||
|
},
|
||||||
|
"frameworks": {
|
||||||
|
"netstandard1.5": {
|
||||||
|
"imports": [ "dnxcore50", "portable-net45+win8" ],
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.NETCore.App": "1.0.0-rc2-23911",
|
||||||
|
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0-*"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace StandaloneApp
|
||||||
|
{
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Hello, World!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,7 @@
|
||||||
{
|
{
|
||||||
"dependencies": { },
|
"compilationOptions": {
|
||||||
|
"emitEntryPoint": true
|
||||||
|
},
|
||||||
"frameworks": {
|
"frameworks": {
|
||||||
"netstandardapp1.5": {
|
"netstandardapp1.5": {
|
||||||
"imports": [
|
"imports": [
|
||||||
|
@ -7,7 +9,7 @@
|
||||||
"portable-net45+win8"
|
"portable-net45+win8"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"NETStandard.Library": "1.0.0-rc2-23901"
|
"Microsoft.NETCore.App": "1.0.0-rc2-23911"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
|
@ -0,0 +1,2 @@
|
||||||
|
# What is this?
|
||||||
|
This is a test wrapped project where we've checked in the binaries. To protect it from the build scripts cleaning the `bin` folder, we've renamed that folder to `bin.keep`. Please don't rename it!
|
|
@ -3,8 +3,8 @@
|
||||||
"netstandardapp1.5": {
|
"netstandardapp1.5": {
|
||||||
"imports": "dnxcore50",
|
"imports": "dnxcore50",
|
||||||
"bin": {
|
"bin": {
|
||||||
"assembly": "bin\\{configuration}\\dnxcore50\\TestLibrary.dll",
|
"assembly": "bin.keep\\{configuration}\\dnxcore50\\TestLibrary.dll",
|
||||||
"pdb": "bin\\{configuration}\\dnxcore50\\TestLibrary.pdb"
|
"pdb": "bin.keep\\{configuration}\\dnxcore50\\TestLibrary.pdb"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,6 +94,8 @@ namespace Microsoft.DotNet.Cli.Build
|
||||||
[Target(nameof(CleanTestPackages))]
|
[Target(nameof(CleanTestPackages))]
|
||||||
public static BuildTargetResult BuildTestAssetPackages(BuildTargetContext c)
|
public static BuildTargetResult BuildTestAssetPackages(BuildTargetContext c)
|
||||||
{
|
{
|
||||||
|
CleanBinObj(c, Path.Combine(c.BuildContext.BuildDirectory, "TestAssets", "TestPackages"));
|
||||||
|
|
||||||
var dotnet = DotNetCli.Stage2;
|
var dotnet = DotNetCli.Stage2;
|
||||||
|
|
||||||
Rmdir(Dirs.TestPackages);
|
Rmdir(Dirs.TestPackages);
|
||||||
|
@ -123,6 +125,8 @@ namespace Microsoft.DotNet.Cli.Build
|
||||||
[Target]
|
[Target]
|
||||||
public static BuildTargetResult BuildTestAssetProjects(BuildTargetContext c)
|
public static BuildTargetResult BuildTestAssetProjects(BuildTargetContext c)
|
||||||
{
|
{
|
||||||
|
CleanBinObj(c, Path.Combine(c.BuildContext.BuildDirectory, "TestAssets", "TestProjects"));
|
||||||
|
|
||||||
var dotnet = DotNetCli.Stage2;
|
var dotnet = DotNetCli.Stage2;
|
||||||
var nobuildFileName = ".noautobuild";
|
var nobuildFileName = ".noautobuild";
|
||||||
string testProjectsRoot = Path.Combine(c.BuildContext.BuildDirectory, "TestAssets", "TestProjects");
|
string testProjectsRoot = Path.Combine(c.BuildContext.BuildDirectory, "TestAssets", "TestProjects");
|
||||||
|
@ -293,7 +297,6 @@ set");
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Verbose("Finish Collecting Visual Studio Environment Variables");
|
c.Verbose("Finish Collecting Visual Studio Environment Variables");
|
||||||
|
|
||||||
return vars;
|
return vars;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,12 +25,12 @@ namespace Microsoft.DotNet.Cli.Utils
|
||||||
{
|
{
|
||||||
if (environment == null)
|
if (environment == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException("environment");
|
throw new ArgumentNullException(nameof(environment));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packagedCommandSpecFactory == null)
|
if (packagedCommandSpecFactory == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException("packagedCommandSpecFactory");
|
throw new ArgumentNullException(nameof(packagedCommandSpecFactory));
|
||||||
}
|
}
|
||||||
|
|
||||||
_environment = environment;
|
_environment = environment;
|
||||||
|
|
|
@ -49,6 +49,9 @@ namespace Microsoft.DotNet.Cli.Utils
|
||||||
var outputBinaryPath = Path.Combine(destinationPath, outputBinaryName);
|
var outputBinaryPath = Path.Combine(destinationPath, outputBinaryName);
|
||||||
var hostBinaryPath = Path.Combine(HostDir, binaryName);
|
var hostBinaryPath = Path.Combine(HostDir, binaryName);
|
||||||
File.Copy(hostBinaryPath, outputBinaryPath, overwrite: true);
|
File.Copy(hostBinaryPath, outputBinaryPath, overwrite: true);
|
||||||
|
|
||||||
|
// Update the last write time so this file can be treated as an output of a build
|
||||||
|
File.SetLastWriteTimeUtc(outputBinaryPath, DateTime.UtcNow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,11 +14,16 @@ using Microsoft.DotNet.ProjectModel.Compilation;
|
||||||
using Microsoft.DotNet.ProjectModel.Graph;
|
using Microsoft.DotNet.ProjectModel.Graph;
|
||||||
using Microsoft.Extensions.DependencyModel;
|
using Microsoft.Extensions.DependencyModel;
|
||||||
using NuGet.Frameworks;
|
using NuGet.Frameworks;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Microsoft.Dotnet.Cli.Compiler.Common
|
namespace Microsoft.Dotnet.Cli.Compiler.Common
|
||||||
{
|
{
|
||||||
public class Executable
|
public class Executable
|
||||||
{
|
{
|
||||||
|
// GROOOOOSS
|
||||||
|
private static readonly string RedistPackageName = "Microsoft.NETCore.App";
|
||||||
|
|
||||||
private readonly ProjectContext _context;
|
private readonly ProjectContext _context;
|
||||||
|
|
||||||
private readonly LibraryExporter _exporter;
|
private readonly LibraryExporter _exporter;
|
||||||
|
@ -71,7 +76,8 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common
|
||||||
{
|
{
|
||||||
WriteDepsFileAndCopyProjectDependencies(_exporter);
|
WriteDepsFileAndCopyProjectDependencies(_exporter);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(_context.RuntimeIdentifier))
|
var emitEntryPoint = _context.ProjectFile.GetCompilerOptions(_context.TargetFramework, _configuration).EmitEntryPoint ?? false;
|
||||||
|
if (emitEntryPoint && !string.IsNullOrEmpty(_context.RuntimeIdentifier))
|
||||||
{
|
{
|
||||||
// TODO: Pick a host based on the RID
|
// TODO: Pick a host based on the RID
|
||||||
CoreHost.CopyTo(_runtimeOutputPath, _context.ProjectFile.Name + Constants.ExeSuffix);
|
CoreHost.CopyTo(_runtimeOutputPath, _context.ProjectFile.Name + Constants.ExeSuffix);
|
||||||
|
@ -106,6 +112,7 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common
|
||||||
private void WriteDepsFileAndCopyProjectDependencies(LibraryExporter exporter)
|
private void WriteDepsFileAndCopyProjectDependencies(LibraryExporter exporter)
|
||||||
{
|
{
|
||||||
WriteDeps(exporter);
|
WriteDeps(exporter);
|
||||||
|
WriteRuntimeConfig(exporter);
|
||||||
|
|
||||||
var projectExports = exporter.GetDependencies(LibraryType.Project);
|
var projectExports = exporter.GetDependencies(LibraryType.Project);
|
||||||
CopyAssemblies(projectExports);
|
CopyAssemblies(projectExports);
|
||||||
|
@ -115,6 +122,37 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common
|
||||||
CopyAssets(packageExports);
|
CopyAssets(packageExports);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void WriteRuntimeConfig(LibraryExporter exporter)
|
||||||
|
{
|
||||||
|
if (!_context.TargetFramework.IsDesktop())
|
||||||
|
{
|
||||||
|
// TODO: Suppress this file if there's nothing to write? RuntimeOutputFiles would have to be updated
|
||||||
|
// in order to prevent breaking incremental compilation...
|
||||||
|
|
||||||
|
var json = new JObject();
|
||||||
|
var runtimeOptions = new JObject();
|
||||||
|
json.Add("runtimeOptions", runtimeOptions);
|
||||||
|
|
||||||
|
var redistExport = exporter
|
||||||
|
.GetAllExports()
|
||||||
|
.FirstOrDefault(l => l.Library.Identity.Name.Equals(RedistPackageName, StringComparison.OrdinalIgnoreCase));
|
||||||
|
if (redistExport != null)
|
||||||
|
{
|
||||||
|
var framework = new JObject(
|
||||||
|
new JProperty("name", redistExport.Library.Identity.Name),
|
||||||
|
new JProperty("version", redistExport.Library.Identity.Version.ToNormalizedString()));
|
||||||
|
runtimeOptions.Add("framework", framework);
|
||||||
|
}
|
||||||
|
|
||||||
|
var runtimeConfigJsonFile = Path.Combine(_runtimeOutputPath, _context.ProjectFile.Name + FileNameSuffixes.RuntimeConfigJson);
|
||||||
|
using (var writer = new JsonTextWriter(new StreamWriter(File.Create(runtimeConfigJsonFile))))
|
||||||
|
{
|
||||||
|
writer.Formatting = Formatting.Indented;
|
||||||
|
json.WriteTo(writer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void WriteDeps(LibraryExporter exporter)
|
public void WriteDeps(LibraryExporter exporter)
|
||||||
{
|
{
|
||||||
var path = Path.Combine(_runtimeOutputPath, _context.ProjectFile.Name + FileNameSuffixes.Deps);
|
var path = Path.Combine(_runtimeOutputPath, _context.ProjectFile.Name + FileNameSuffixes.Deps);
|
||||||
|
@ -128,7 +166,7 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common
|
||||||
|
|
||||||
var exports = exporter.GetAllExports().ToArray();
|
var exports = exporter.GetAllExports().ToArray();
|
||||||
var dependencyContext = new DependencyContextBuilder().Build(
|
var dependencyContext = new DependencyContextBuilder().Build(
|
||||||
compilerOptions: includeCompile? compilerOptions: null,
|
compilerOptions: includeCompile ? compilerOptions : null,
|
||||||
compilationExports: includeCompile ? exports : null,
|
compilationExports: includeCompile ? exports : null,
|
||||||
runtimeExports: exports,
|
runtimeExports: exports,
|
||||||
portable: string.IsNullOrEmpty(_context.RuntimeIdentifier),
|
portable: string.IsNullOrEmpty(_context.RuntimeIdentifier),
|
||||||
|
@ -141,10 +179,8 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common
|
||||||
{
|
{
|
||||||
writer.Write(dependencyContext, fileStream);
|
writer.Write(dependencyContext, fileStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void GenerateBindingRedirects(LibraryExporter exporter)
|
public void GenerateBindingRedirects(LibraryExporter exporter)
|
||||||
{
|
{
|
||||||
var outputName = _outputPaths.RuntimeFiles.Assembly;
|
var outputName = _outputPaths.RuntimeFiles.Assembly;
|
||||||
|
|
|
@ -15,6 +15,7 @@ namespace Microsoft.DotNet.ProjectModel.Compilation
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
public string RelativePath { get; }
|
public string RelativePath { get; }
|
||||||
public string ResolvedPath { get; }
|
public string ResolvedPath { get; }
|
||||||
|
public string FileName => Path.GetFileName(RelativePath);
|
||||||
public Action<Stream, Stream> Transform { get; set; }
|
public Action<Stream, Stream> Transform { get; set; }
|
||||||
|
|
||||||
public LibraryAsset(string name, string relativePath, string resolvedPath, Action<Stream, Stream> transform = null)
|
public LibraryAsset(string name, string relativePath, string resolvedPath, Action<Stream, Stream> transform = null)
|
||||||
|
|
|
@ -7,6 +7,7 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
{
|
{
|
||||||
public const string Deps = ".deps";
|
public const string Deps = ".deps";
|
||||||
public const string DepsJson = ".deps.json";
|
public const string DepsJson = ".deps.json";
|
||||||
|
public const string RuntimeConfigJson = ".runtimeconfig.json";
|
||||||
|
|
||||||
public static PlatformFileNameSuffixes CurrentPlatform
|
public static PlatformFileNameSuffixes CurrentPlatform
|
||||||
{
|
{
|
||||||
|
|
|
@ -70,11 +70,7 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
|
|
||||||
var compilationFiles = new CompilationOutputFiles(compilationOutputPath, project, configuration, framework);
|
var compilationFiles = new CompilationOutputFiles(compilationOutputPath, project, configuration, framework);
|
||||||
|
|
||||||
RuntimeOutputFiles runtimeFiles = null;
|
RuntimeOutputFiles runtimeFiles = new RuntimeOutputFiles(runtimeOutputPath, project, configuration, framework, runtimeIdentifier);
|
||||||
if (runtimeOutputPath != null)
|
|
||||||
{
|
|
||||||
runtimeFiles = new RuntimeOutputFiles(runtimeOutputPath, project, configuration, framework);
|
|
||||||
}
|
|
||||||
return new OutputPaths(intermediateOutputPath, compilationOutputPath, runtimeOutputPath, compilationFiles, runtimeFiles);
|
return new OutputPaths(intermediateOutputPath, compilationOutputPath, runtimeOutputPath, compilationFiles, runtimeFiles);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,6 +140,12 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
|
|
||||||
public ProjectContext CreateRuntimeContext(IEnumerable<string> runtimeIdentifiers)
|
public ProjectContext CreateRuntimeContext(IEnumerable<string> runtimeIdentifiers)
|
||||||
{
|
{
|
||||||
|
// Temporary until we have removed RID inference from NuGet
|
||||||
|
if(TargetFramework.IsCompileOnly)
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if there are any runtime targets (i.e. are we portable)
|
// Check if there are any runtime targets (i.e. are we portable)
|
||||||
var standalone = LockFile.Targets
|
var standalone = LockFile.Targets
|
||||||
.Where(t => t.TargetFramework.Equals(TargetFramework))
|
.Where(t => t.TargetFramework.Equals(TargetFramework))
|
||||||
|
|
|
@ -9,11 +9,15 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
{
|
{
|
||||||
public class RuntimeOutputFiles : CompilationOutputFiles
|
public class RuntimeOutputFiles : CompilationOutputFiles
|
||||||
{
|
{
|
||||||
|
private readonly string _runtimeIdentifier;
|
||||||
|
|
||||||
public RuntimeOutputFiles(string basePath,
|
public RuntimeOutputFiles(string basePath,
|
||||||
Project project,
|
Project project,
|
||||||
string configuration,
|
string configuration,
|
||||||
NuGetFramework framework) : base(basePath, project, configuration, framework)
|
NuGetFramework framework,
|
||||||
|
string runtimeIdentifier) : base(basePath, project, configuration, framework)
|
||||||
{
|
{
|
||||||
|
_runtimeIdentifier = runtimeIdentifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Executable
|
public string Executable
|
||||||
|
@ -39,6 +43,7 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
return Path.ChangeExtension(Assembly, FileNameSuffixes.Deps);
|
return Path.ChangeExtension(Assembly, FileNameSuffixes.Deps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string DepsJson
|
public string DepsJson
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -47,6 +52,14 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string RuntimeConfigJson
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Path.ChangeExtension(Assembly, FileNameSuffixes.RuntimeConfigJson);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public string Config
|
public string Config
|
||||||
{
|
{
|
||||||
get { return Assembly + ".config"; }
|
get { return Assembly + ".config"; }
|
||||||
|
@ -59,20 +72,28 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
yield return file;
|
yield return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Project.HasRuntimeOutput(Config))
|
||||||
|
{
|
||||||
|
if (!Framework.IsDesktop())
|
||||||
|
{
|
||||||
|
yield return Deps;
|
||||||
|
yield return DepsJson;
|
||||||
|
yield return RuntimeConfigJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the project actually has an entry point AND we're doing a standalone build
|
||||||
|
var hasEntryPoint = Project.GetCompilerOptions(targetFramework: null, configurationName: Configuration).EmitEntryPoint ?? false;
|
||||||
|
if (hasEntryPoint && !string.IsNullOrEmpty(_runtimeIdentifier))
|
||||||
|
{
|
||||||
|
// Yield the executable
|
||||||
|
yield return Executable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (File.Exists(Config))
|
if (File.Exists(Config))
|
||||||
{
|
{
|
||||||
yield return Config;
|
yield return Config;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (File.Exists(Deps))
|
|
||||||
{
|
|
||||||
yield return Deps;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (File.Exists(DepsJson))
|
|
||||||
{
|
|
||||||
yield return DepsJson;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -420,12 +420,6 @@ namespace Microsoft.DotNet.Tools.Build
|
||||||
private void MakeRunnable()
|
private void MakeRunnable()
|
||||||
{
|
{
|
||||||
var runtimeContext = _rootProject.CreateRuntimeContext(_args.GetRuntimes());
|
var runtimeContext = _rootProject.CreateRuntimeContext(_args.GetRuntimes());
|
||||||
if(_args.PortableMode)
|
|
||||||
{
|
|
||||||
// HACK: Force the use of the portable target
|
|
||||||
runtimeContext = _rootProject;
|
|
||||||
}
|
|
||||||
|
|
||||||
var outputPaths = runtimeContext.GetOutputPaths(_args.ConfigValue, _args.BuildBasePathValue, _args.OutputValue);
|
var outputPaths = runtimeContext.GetOutputPaths(_args.ConfigValue, _args.BuildBasePathValue, _args.OutputValue);
|
||||||
var libraryExporter = runtimeContext.CreateExporter(_args.ConfigValue, _args.BuildBasePathValue);
|
var libraryExporter = runtimeContext.CreateExporter(_args.ConfigValue, _args.BuildBasePathValue);
|
||||||
|
|
||||||
|
@ -436,6 +430,7 @@ namespace Microsoft.DotNet.Tools.Build
|
||||||
CopyCompilationOutput(outputPaths);
|
CopyCompilationOutput(outputPaths);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var options = runtimeContext.ProjectFile.GetCompilerOptions(runtimeContext.TargetFramework, _args.ConfigValue);
|
||||||
var executable = new Executable(runtimeContext, outputPaths, libraryExporter, _args.ConfigValue);
|
var executable = new Executable(runtimeContext, outputPaths, libraryExporter, _args.ConfigValue);
|
||||||
executable.MakeCompilationOutputRunnable();
|
executable.MakeCompilationOutputRunnable();
|
||||||
|
|
||||||
|
@ -445,7 +440,6 @@ namespace Microsoft.DotNet.Tools.Build
|
||||||
// Workaround: CoreCLR packaging doesn't include side by side mscorlib, so copy it at build
|
// Workaround: CoreCLR packaging doesn't include side by side mscorlib, so copy it at build
|
||||||
// time. See: https://github.com/dotnet/cli/issues/1374
|
// time. See: https://github.com/dotnet/cli/issues/1374
|
||||||
private static void PatchMscorlibNextToCoreClr(ProjectContext context, string config)
|
private static void PatchMscorlibNextToCoreClr(ProjectContext context, string config)
|
||||||
{
|
|
||||||
{
|
{
|
||||||
foreach (var exp in context.CreateExporter(config).GetAllExports())
|
foreach (var exp in context.CreateExporter(config).GetAllExports())
|
||||||
{
|
{
|
||||||
|
@ -465,7 +459,6 @@ namespace Microsoft.DotNet.Tools.Build
|
||||||
File.Copy(mscorlibFile, Path.Combine(coreclrDir, Path.GetFileName(mscorlibFile)), overwrite: true);
|
File.Copy(mscorlibFile, Path.Combine(coreclrDir, Path.GetFileName(mscorlibFile)), overwrite: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static ISet<ProjectDescription> Sort(Dictionary<string, ProjectDescription> projects)
|
private static ISet<ProjectDescription> Sort(Dictionary<string, ProjectDescription> projects)
|
||||||
{
|
{
|
||||||
|
@ -533,12 +526,16 @@ namespace Microsoft.DotNet.Tools.Build
|
||||||
// input: dependencies
|
// input: dependencies
|
||||||
AddDependencies(dependencies, compilerIO);
|
AddDependencies(dependencies, compilerIO);
|
||||||
|
|
||||||
var allOutputPath = new List<string>(calculator.CompilationFiles.All());
|
var allOutputPath = new HashSet<string>(calculator.CompilationFiles.All());
|
||||||
if (isRootProject && project.ProjectFile.HasRuntimeOutput(buildConfiguration))
|
if (isRootProject && project.ProjectFile.HasRuntimeOutput(buildConfiguration))
|
||||||
{
|
{
|
||||||
var runtimeContext = project.CreateRuntimeContext(_args.GetRuntimes());
|
var runtimeContext = project.CreateRuntimeContext(_args.GetRuntimes());
|
||||||
allOutputPath.AddRange(runtimeContext.GetOutputPaths(buildConfiguration, buildBasePath, outputPath).RuntimeFiles.All());
|
foreach (var path in runtimeContext.GetOutputPaths(buildConfiguration, buildBasePath, outputPath).RuntimeFiles.All())
|
||||||
|
{
|
||||||
|
allOutputPath.Add(path);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// output: compiler outputs
|
// output: compiler outputs
|
||||||
foreach (var path in allOutputPath)
|
foreach (var path in allOutputPath)
|
||||||
{
|
{
|
||||||
|
|
|
@ -29,7 +29,6 @@ namespace Microsoft.DotNet.Tools.Compiler
|
||||||
private CommandOption _runtimeOption;
|
private CommandOption _runtimeOption;
|
||||||
private CommandOption _versionSuffixOption;
|
private CommandOption _versionSuffixOption;
|
||||||
private CommandOption _configurationOption;
|
private CommandOption _configurationOption;
|
||||||
private CommandOption _portableOption;
|
|
||||||
private CommandArgument _projectArgument;
|
private CommandArgument _projectArgument;
|
||||||
private CommandOption _nativeOption;
|
private CommandOption _nativeOption;
|
||||||
private CommandOption _archOption;
|
private CommandOption _archOption;
|
||||||
|
@ -55,7 +54,6 @@ namespace Microsoft.DotNet.Tools.Compiler
|
||||||
public bool IsCppModeValue { get; set; }
|
public bool IsCppModeValue { get; set; }
|
||||||
public string AppDepSdkPathValue { get; set; }
|
public string AppDepSdkPathValue { get; set; }
|
||||||
public string CppCompilerFlagsValue { get; set; }
|
public string CppCompilerFlagsValue { get; set; }
|
||||||
public bool PortableMode { get; set; }
|
|
||||||
|
|
||||||
// workaround: CommandLineApplication is internal therefore I cannot make _app protected so baseclasses can add their own params
|
// workaround: CommandLineApplication is internal therefore I cannot make _app protected so baseclasses can add their own params
|
||||||
private readonly Dictionary<string, CommandOption> baseClassOptions;
|
private readonly Dictionary<string, CommandOption> baseClassOptions;
|
||||||
|
@ -86,9 +84,6 @@ namespace Microsoft.DotNet.Tools.Compiler
|
||||||
_versionSuffixOption = _app.Option("--version-suffix <VERSION_SUFFIX>", "Defines what `*` should be replaced with in version field in project.json", CommandOptionType.SingleValue);
|
_versionSuffixOption = _app.Option("--version-suffix <VERSION_SUFFIX>", "Defines what `*` should be replaced with in version field in project.json", CommandOptionType.SingleValue);
|
||||||
_projectArgument = _app.Argument("<PROJECT>", "The project to compile, defaults to the current directory. Can be a path to a project.json or a project directory");
|
_projectArgument = _app.Argument("<PROJECT>", "The project to compile, defaults to the current directory. Can be a path to a project.json or a project directory");
|
||||||
|
|
||||||
// HACK: Allow us to treat a project as though it was portable by ignoring the runtime-specific targets. This is temporary until RID inference is removed from NuGet
|
|
||||||
_portableOption = _app.Option("--portable", "TEMPORARY: Enforces portable build/publish mode", CommandOptionType.NoValue);
|
|
||||||
|
|
||||||
// Native Args
|
// Native Args
|
||||||
_nativeOption = _app.Option("-n|--native", "Compiles source to native machine code.", CommandOptionType.NoValue);
|
_nativeOption = _app.Option("-n|--native", "Compiles source to native machine code.", CommandOptionType.NoValue);
|
||||||
_archOption = _app.Option("-a|--arch <ARCH>", "The architecture for which to compile. x64 only currently supported.", CommandOptionType.SingleValue);
|
_archOption = _app.Option("-a|--arch <ARCH>", "The architecture for which to compile. x64 only currently supported.", CommandOptionType.SingleValue);
|
||||||
|
@ -122,7 +117,6 @@ namespace Microsoft.DotNet.Tools.Compiler
|
||||||
ConfigValue = _configurationOption.Value() ?? Constants.DefaultConfiguration;
|
ConfigValue = _configurationOption.Value() ?? Constants.DefaultConfiguration;
|
||||||
RuntimeValue = _runtimeOption.Value();
|
RuntimeValue = _runtimeOption.Value();
|
||||||
VersionSuffixValue = _versionSuffixOption.Value();
|
VersionSuffixValue = _versionSuffixOption.Value();
|
||||||
PortableMode = _portableOption.HasValue();
|
|
||||||
|
|
||||||
IsNativeValue = _nativeOption.HasValue();
|
IsNativeValue = _nativeOption.HasValue();
|
||||||
ArchValue = _archOption.Value();
|
ArchValue = _archOption.Value();
|
||||||
|
|
|
@ -114,7 +114,7 @@ namespace Microsoft.DotNet.Tools.Compiler
|
||||||
var dependencyContext = new DependencyContextBuilder().Build(compilationOptions,
|
var dependencyContext = new DependencyContextBuilder().Build(compilationOptions,
|
||||||
allExports,
|
allExports,
|
||||||
allExports,
|
allExports,
|
||||||
args.PortableMode,
|
true, // For now, just assume portable mode in the legacy deps file (this is going away soon anyway)
|
||||||
context.TargetFramework,
|
context.TargetFramework,
|
||||||
context.RuntimeIdentifier ?? string.Empty);
|
context.RuntimeIdentifier ?? string.Empty);
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace Microsoft.DotNet.Tools.Publish
|
||||||
public string Runtime { get; set; }
|
public string Runtime { get; set; }
|
||||||
public bool NativeSubdirectories { get; set; }
|
public bool NativeSubdirectories { get; set; }
|
||||||
public NuGetFramework NugetFramework { get; set; }
|
public NuGetFramework NugetFramework { get; set; }
|
||||||
public IEnumerable<ProjectContext> ProjectContexts { get; set; }
|
public IList<ProjectContext> ProjectContexts { get; set; }
|
||||||
public string VersionSuffix { get; set; }
|
public string VersionSuffix { get; set; }
|
||||||
public int NumberOfProjects { get; private set; }
|
public int NumberOfProjects { get; private set; }
|
||||||
public int NumberOfPublishedProjects { get; private set; }
|
public int NumberOfPublishedProjects { get; private set; }
|
||||||
|
@ -47,7 +47,7 @@ namespace Microsoft.DotNet.Tools.Publish
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ProjectContexts = SelectContexts(ProjectPath, NugetFramework, Runtime);
|
ProjectContexts = SelectContexts(ProjectPath, NugetFramework, Runtime).ToList();
|
||||||
if (!ProjectContexts.Any())
|
if (!ProjectContexts.Any())
|
||||||
{
|
{
|
||||||
string errMsg = $"'{ProjectPath}' cannot be published for '{Framework ?? "<no framework provided>"}' '{Runtime ?? "<no runtime provided>"}'";
|
string errMsg = $"'{ProjectPath}' cannot be published for '{Framework ?? "<no framework provided>"}' '{Runtime ?? "<no runtime provided>"}'";
|
||||||
|
@ -84,7 +84,12 @@ namespace Microsoft.DotNet.Tools.Publish
|
||||||
/// <returns>Return 0 if successful else return non-zero</returns>
|
/// <returns>Return 0 if successful else return non-zero</returns>
|
||||||
private bool PublishProjectContext(ProjectContext context, string buildBasePath, string outputPath, string configuration, bool nativeSubdirectories)
|
private bool PublishProjectContext(ProjectContext context, string buildBasePath, string outputPath, string configuration, bool nativeSubdirectories)
|
||||||
{
|
{
|
||||||
Reporter.Output.WriteLine($"Publishing {context.RootProject.Identity.Name.Yellow()} for {context.TargetFramework.DotNetFrameworkName.Yellow()}/{context.RuntimeIdentifier.Yellow()}");
|
var target = context.TargetFramework.DotNetFrameworkName;
|
||||||
|
if (!string.IsNullOrEmpty(context.RuntimeIdentifier))
|
||||||
|
{
|
||||||
|
target = $"{target}/{context.RuntimeIdentifier}";
|
||||||
|
}
|
||||||
|
Reporter.Output.WriteLine($"Publishing {context.RootProject.Identity.Name.Yellow()} for {target.Yellow()}");
|
||||||
|
|
||||||
var options = context.ProjectFile.GetCompilerOptions(context.TargetFramework, configuration);
|
var options = context.ProjectFile.GetCompilerOptions(context.TargetFramework, configuration);
|
||||||
var outputPaths = context.GetOutputPaths(configuration, buildBasePath, outputPath);
|
var outputPaths = context.GetOutputPaths(configuration, buildBasePath, outputPath);
|
||||||
|
@ -115,13 +120,17 @@ namespace Microsoft.DotNet.Tools.Publish
|
||||||
var args = new List<string>() {
|
var args = new List<string>() {
|
||||||
"--framework",
|
"--framework",
|
||||||
$"{context.TargetFramework.DotNetFrameworkName}",
|
$"{context.TargetFramework.DotNetFrameworkName}",
|
||||||
"--runtime",
|
|
||||||
context.RuntimeIdentifier,
|
|
||||||
"--configuration",
|
"--configuration",
|
||||||
configuration,
|
configuration,
|
||||||
context.ProjectFile.ProjectDirectory
|
context.ProjectFile.ProjectDirectory
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(context.RuntimeIdentifier))
|
||||||
|
{
|
||||||
|
args.Insert(0, context.RuntimeIdentifier);
|
||||||
|
args.Insert(0, "--runtime");
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(VersionSuffix))
|
if (!string.IsNullOrEmpty(VersionSuffix))
|
||||||
{
|
{
|
||||||
args.Add("--version-suffix");
|
args.Add("--version-suffix");
|
||||||
|
@ -147,23 +156,43 @@ namespace Microsoft.DotNet.Tools.Publish
|
||||||
{
|
{
|
||||||
Reporter.Verbose.WriteLine($"Publishing {export.Library.Identity.ToString().Green().Bold()} ...");
|
Reporter.Verbose.WriteLine($"Publishing {export.Library.Identity.ToString().Green().Bold()} ...");
|
||||||
|
|
||||||
PublishFiles(export.RuntimeAssemblies, outputPath, nativeSubdirectories: false);
|
PublishFiles(export.RuntimeAssemblies, outputPath, nativeSubdirectories: false, preserveRelativePath: false);
|
||||||
PublishFiles(export.NativeLibraries, outputPath, nativeSubdirectories);
|
PublishFiles(export.NativeLibraries, outputPath, nativeSubdirectories, preserveRelativePath: false);
|
||||||
export.RuntimeAssets.StructuredCopyTo(outputPath, outputPaths.IntermediateOutputDirectoryPath);
|
export.RuntimeAssets.StructuredCopyTo(outputPath, outputPaths.IntermediateOutputDirectoryPath);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(context.RuntimeIdentifier))
|
||||||
|
{
|
||||||
|
var assets = export.RuntimeTargets.SelectMany(t => Enumerable.Concat(t.NativeLibraries, t.RuntimeAssemblies));
|
||||||
|
PublishFiles(assets, outputPath, nativeSubdirectories: false, preserveRelativePath: true);
|
||||||
|
}
|
||||||
|
|
||||||
if (options.PreserveCompilationContext.GetValueOrDefault())
|
if (options.PreserveCompilationContext.GetValueOrDefault())
|
||||||
{
|
{
|
||||||
PublishRefs(export, outputPath);
|
PublishRefs(export, outputPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (context.ProjectFile.HasRuntimeOutput(configuration) && !context.TargetFramework.IsDesktop())
|
||||||
|
{
|
||||||
|
// Get the output paths used by the call to `dotnet build` above (since we didn't pass `--output`, they will be different from
|
||||||
|
// our current output paths)
|
||||||
|
var buildOutputPaths = context.GetOutputPaths(configuration, buildBasePath);
|
||||||
|
PublishFiles(
|
||||||
|
new[] {
|
||||||
|
buildOutputPaths.RuntimeFiles.Deps,
|
||||||
|
buildOutputPaths.RuntimeFiles.DepsJson,
|
||||||
|
buildOutputPaths.RuntimeFiles.RuntimeConfigJson
|
||||||
|
},
|
||||||
|
outputPath);
|
||||||
|
}
|
||||||
|
|
||||||
var contentFiles = new ContentFiles(context);
|
var contentFiles = new ContentFiles(context);
|
||||||
contentFiles.StructuredCopyTo(outputPath);
|
contentFiles.StructuredCopyTo(outputPath);
|
||||||
|
|
||||||
// Publish a host if this is an application
|
// Publish a host if this is an application
|
||||||
if (options.EmitEntryPoint.GetValueOrDefault())
|
if (options.EmitEntryPoint.GetValueOrDefault() && !string.IsNullOrEmpty(context.RuntimeIdentifier))
|
||||||
{
|
{
|
||||||
Reporter.Verbose.WriteLine($"Making {context.ProjectFile.Name.Cyan()} runnable ...");
|
Reporter.Verbose.WriteLine($"Copying native host to output to create fully standalone output.");
|
||||||
PublishHost(context, outputPath);
|
PublishHost(context, outputPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,18 +257,23 @@ namespace Microsoft.DotNet.Tools.Publish
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void PublishFiles(IEnumerable<LibraryAsset> files, string outputPath, bool nativeSubdirectories)
|
private static void PublishFiles(IEnumerable<LibraryAsset> files, string outputPath, bool nativeSubdirectories, bool preserveRelativePath)
|
||||||
{
|
{
|
||||||
foreach (var file in files)
|
foreach (var file in files)
|
||||||
{
|
{
|
||||||
var destinationDirectory = DetermineFileDestinationDirectory(file, outputPath, nativeSubdirectories);
|
var destinationDirectory = DetermineFileDestinationDirectory(file, outputPath, nativeSubdirectories);
|
||||||
|
|
||||||
|
if (preserveRelativePath)
|
||||||
|
{
|
||||||
|
destinationDirectory = Path.Combine(destinationDirectory, Path.GetDirectoryName(file.RelativePath));
|
||||||
|
}
|
||||||
|
|
||||||
if (!Directory.Exists(destinationDirectory))
|
if (!Directory.Exists(destinationDirectory))
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(destinationDirectory);
|
Directory.CreateDirectory(destinationDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
File.Copy(file.ResolvedPath, Path.Combine(destinationDirectory, Path.GetFileName(file.ResolvedPath)), overwrite: true);
|
File.Copy(file.ResolvedPath, Path.Combine(destinationDirectory, file.FileName), overwrite: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,29 +306,46 @@ namespace Microsoft.DotNet.Tools.Publish
|
||||||
return candidate;
|
return candidate;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<ProjectContext> SelectContexts(string projectPath, NuGetFramework framework, string runtime)
|
private IEnumerable<ProjectContext> SelectContexts(string projectPath, NuGetFramework framework, string runtime)
|
||||||
{
|
{
|
||||||
var allContexts = ProjectContext.CreateContextForEachTarget(projectPath);
|
var allContexts = ProjectContext.CreateContextForEachTarget(projectPath).ToList();
|
||||||
|
var frameworks = framework == null ?
|
||||||
|
allContexts.Select(c => c.TargetFramework).Distinct().ToArray() :
|
||||||
|
new[] { framework };
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(runtime))
|
if (string.IsNullOrEmpty(runtime))
|
||||||
{
|
{
|
||||||
// Nothing was specified, so figure out what the candidate runtime identifiers are and try each of them
|
// For each framework, find the best matching RID item
|
||||||
// Temporary until #619 is resolved
|
var candidates = PlatformServices.Default.Runtime.GetAllCandidateRuntimeIdentifiers();
|
||||||
foreach (var candidate in PlatformServices.Default.Runtime.GetAllCandidateRuntimeIdentifiers())
|
return frameworks.Select(f => FindBestTarget(f, allContexts, candidates));
|
||||||
{
|
|
||||||
var contexts = GetMatchingProjectContexts(allContexts, framework, candidate);
|
|
||||||
if (contexts.Any())
|
|
||||||
{
|
|
||||||
return contexts;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Enumerable.Empty<ProjectContext>();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return GetMatchingProjectContexts(allContexts, framework, runtime);
|
return frameworks.SelectMany(f => allContexts.Where(c =>
|
||||||
|
Equals(c.TargetFramework, f) &&
|
||||||
|
string.Equals(c.RuntimeIdentifier, runtime, StringComparison.Ordinal)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ProjectContext FindBestTarget(NuGetFramework f, List<ProjectContext> allContexts, IEnumerable<string> candidates)
|
||||||
|
{
|
||||||
|
foreach (var candidate in candidates)
|
||||||
|
{
|
||||||
|
var target = allContexts.FirstOrDefault(c =>
|
||||||
|
Equals(c.TargetFramework, f) &&
|
||||||
|
string.Equals(c.RuntimeIdentifier, candidate, StringComparison.Ordinal));
|
||||||
|
if (target != null)
|
||||||
|
{
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No RID-specific target found, use the RID-less target and publish portable
|
||||||
|
return allContexts.FirstOrDefault(c =>
|
||||||
|
Equals(c.TargetFramework, f) &&
|
||||||
|
string.IsNullOrEmpty(c.RuntimeIdentifier));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Return the matching framework/runtime ProjectContext.
|
/// Return the matching framework/runtime ProjectContext.
|
||||||
/// If 'framework' or 'runtimeIdentifier' is null or empty then it matches with any.
|
/// If 'framework' or 'runtimeIdentifier' is null or empty then it matches with any.
|
||||||
|
|
|
@ -29,7 +29,6 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
|
||||||
private readonly bool _noIncremental;
|
private readonly bool _noIncremental;
|
||||||
private readonly bool _noDependencies;
|
private readonly bool _noDependencies;
|
||||||
private readonly string _runtime;
|
private readonly string _runtime;
|
||||||
private readonly bool _forcePortable;
|
|
||||||
|
|
||||||
private string OutputOption
|
private string OutputOption
|
||||||
{
|
{
|
||||||
|
@ -41,16 +40,6 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string ForcePortableOption
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _forcePortable ?
|
|
||||||
"--portable" :
|
|
||||||
string.Empty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private string BuildBasePathOption
|
private string BuildBasePathOption
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -228,9 +217,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
|
||||||
string cppCompilerFlags="",
|
string cppCompilerFlags="",
|
||||||
bool buildProfile=true,
|
bool buildProfile=true,
|
||||||
bool noIncremental=false,
|
bool noIncremental=false,
|
||||||
bool noDependencies=false,
|
bool noDependencies=false)
|
||||||
bool forcePortable=false
|
|
||||||
)
|
|
||||||
: base("dotnet")
|
: base("dotnet")
|
||||||
{
|
{
|
||||||
_projectPath = projectPath;
|
_projectPath = projectPath;
|
||||||
|
@ -253,7 +240,6 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
|
||||||
_buildProfile = buildProfile;
|
_buildProfile = buildProfile;
|
||||||
_noIncremental = noIncremental;
|
_noIncremental = noIncremental;
|
||||||
_noDependencies = noDependencies;
|
_noDependencies = noDependencies;
|
||||||
_forcePortable = forcePortable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override CommandResult Execute(string args = "")
|
public override CommandResult Execute(string args = "")
|
||||||
|
@ -277,7 +263,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
|
||||||
|
|
||||||
private string BuildArgs()
|
private string BuildArgs()
|
||||||
{
|
{
|
||||||
return $"{BuildProfile} {ForcePortableOption} {NoDependencies} {NoIncremental} \"{_projectPath}\" {OutputOption} {BuildBasePathOption} {ConfigurationOption} {FrameworkOption} {RuntimeOption} {VersionSuffixOption} {NoHostOption} {NativeOption} {ArchitectureOption} {IlcArgsOption} {IlcPathOption} {AppDepSDKPathOption} {NativeCppModeOption} {CppCompilerFlagsOption}";
|
return $"{BuildProfile} {NoDependencies} {NoIncremental} \"{_projectPath}\" {OutputOption} {BuildBasePathOption} {ConfigurationOption} {FrameworkOption} {RuntimeOption} {VersionSuffixOption} {NoHostOption} {NativeOption} {ArchitectureOption} {IlcArgsOption} {IlcPathOption} {AppDepSDKPathOption} {NativeCppModeOption} {CppCompilerFlagsOption}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,12 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
// 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.
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
|
||||||
using System;
|
using Microsoft.DotNet.Cli.Utils;
|
||||||
using System.Collections.Generic;
|
using Microsoft.DotNet.ProjectModel;
|
||||||
|
using Microsoft.Extensions.PlatformAbstractions;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.DotNet.Cli.Utils;
|
|
||||||
using Microsoft.DotNet.ProjectModel;
|
|
||||||
using Microsoft.DotNet.Tools.Test.Utilities;
|
|
||||||
using Microsoft.Extensions.PlatformAbstractions;
|
|
||||||
|
|
||||||
namespace Microsoft.DotNet.Tools.Test.Utilities
|
namespace Microsoft.DotNet.Tools.Test.Utilities
|
||||||
{
|
{
|
||||||
|
@ -18,14 +14,14 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
|
||||||
{
|
{
|
||||||
private const string PublishSubfolderName = "publish";
|
private const string PublishSubfolderName = "publish";
|
||||||
|
|
||||||
private Project _project;
|
private readonly Project _project;
|
||||||
private string _path;
|
private readonly string _path;
|
||||||
private string _framework;
|
private readonly string _framework;
|
||||||
private string _runtime;
|
private readonly string _runtime;
|
||||||
private string _config;
|
private readonly string _config;
|
||||||
private string _output;
|
private readonly string _output;
|
||||||
|
|
||||||
public PublishCommand(string projectPath, string framework="", string runtime="", string output="", string config="")
|
public PublishCommand(string projectPath, string framework = "", string runtime = "", string output = "", string config = "", bool forcePortable = false)
|
||||||
: base("dotnet")
|
: base("dotnet")
|
||||||
{
|
{
|
||||||
_path = projectPath;
|
_path = projectPath;
|
||||||
|
@ -36,7 +32,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
|
||||||
_config = config;
|
_config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override CommandResult Execute(string args="")
|
public override CommandResult Execute(string args = "")
|
||||||
{
|
{
|
||||||
args = $"publish {BuildArgs()} {args}";
|
args = $"publish {BuildArgs()} {args}";
|
||||||
return base.Execute(args);
|
return base.Execute(args);
|
||||||
|
@ -48,34 +44,33 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
|
||||||
return base.ExecuteWithCapturedOutput(args);
|
return base.ExecuteWithCapturedOutput(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ProjectName
|
public string ProjectName => _project.Name;
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _project.Name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private string BuildRelativeOutputPath()
|
private string BuildRelativeOutputPath(bool portable)
|
||||||
{
|
{
|
||||||
// lets try to build an approximate output path
|
// lets try to build an approximate output path
|
||||||
string config = string.IsNullOrEmpty(_config) ? "Debug" : _config;
|
string config = string.IsNullOrEmpty(_config) ? "Debug" : _config;
|
||||||
string framework = string.IsNullOrEmpty(_framework) ?
|
string framework = string.IsNullOrEmpty(_framework) ?
|
||||||
_project.GetTargetFrameworks().First().FrameworkName.GetShortFolderName() : _framework;
|
_project.GetTargetFrameworks().First().FrameworkName.GetShortFolderName() : _framework;
|
||||||
string runtime = string.IsNullOrEmpty(_runtime) ? PlatformServices.Default.Runtime.GetLegacyRestoreRuntimeIdentifier() : _runtime;
|
if (!portable)
|
||||||
string output = Path.Combine(config, framework, runtime, PublishSubfolderName);
|
{
|
||||||
|
var runtime = string.IsNullOrEmpty(_runtime) ? PlatformServices.Default.Runtime.GetLegacyRestoreRuntimeIdentifier() : _runtime;
|
||||||
return output;
|
return Path.Combine(config, framework, runtime, PublishSubfolderName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Path.Combine(config, framework, PublishSubfolderName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DirectoryInfo GetOutputDirectory()
|
public DirectoryInfo GetOutputDirectory(bool portable = false)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(_output))
|
if (!string.IsNullOrEmpty(_output))
|
||||||
{
|
{
|
||||||
return new DirectoryInfo(_output);
|
return new DirectoryInfo(_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
string output = Path.Combine(_project.ProjectDirectory, "bin", BuildRelativeOutputPath());
|
string output = Path.Combine(_project.ProjectDirectory, "bin", BuildRelativeOutputPath(portable));
|
||||||
return new DirectoryInfo(output);
|
return new DirectoryInfo(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,27 +83,12 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
|
||||||
|
|
||||||
private string BuildArgs()
|
private string BuildArgs()
|
||||||
{
|
{
|
||||||
return $"{_path} {GetFrameworkOption()} {GetRuntimeOption()} {GetOutputOption()} {GetConfigOption()}";
|
return $"{_path} {FrameworkOption} {RuntimeOption} {OutputOption} {ConfigOption}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetFrameworkOption()
|
private string FrameworkOption => string.IsNullOrEmpty(_framework) ? "" : $"-f {_framework}";
|
||||||
{
|
private string RuntimeOption => string.IsNullOrEmpty(_runtime) ? "" : $"-r {_runtime}";
|
||||||
return string.IsNullOrEmpty(_framework) ? "" : $"-f {_framework}";
|
private string OutputOption => string.IsNullOrEmpty(_output) ? "" : $"-o \"{_output}\"";
|
||||||
}
|
private string ConfigOption => string.IsNullOrEmpty(_config) ? "" : $"-c {_output}";
|
||||||
|
|
||||||
private string GetRuntimeOption()
|
|
||||||
{
|
|
||||||
return string.IsNullOrEmpty(_runtime) ? "" : $"-r {_runtime}";
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetOutputOption()
|
|
||||||
{
|
|
||||||
return string.IsNullOrEmpty(_output) ? "" : $"-o \"{_output}\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetConfigOption()
|
|
||||||
{
|
|
||||||
return string.IsNullOrEmpty(_config) ? "" : $"-c {_output}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,11 +9,11 @@ namespace Microsoft.DotNet.Tools.Builder.Tests
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ErrorOccursWhenBuildingPortableProjectToSpecificOutputPathWithoutSpecifyingFramework()
|
public void ErrorOccursWhenBuildingPortableProjectToSpecificOutputPathWithoutSpecifyingFramework()
|
||||||
{
|
{
|
||||||
var testInstance = TestAssetsManager.CreateTestInstance("BuildTestPortableProject")
|
var testInstance = TestAssetsManager.CreateTestInstance("PortableTests")
|
||||||
.WithLockFiles();
|
.WithLockFiles();
|
||||||
|
|
||||||
var result = new BuildCommand(
|
var result = new BuildCommand(
|
||||||
projectPath: testInstance.TestRoot,
|
projectPath: Path.Combine(testInstance.TestRoot, "PortableApp"),
|
||||||
output: Path.Combine(testInstance.TestRoot, "out"))
|
output: Path.Combine(testInstance.TestRoot, "out"))
|
||||||
.ExecuteWithCapturedOutput();
|
.ExecuteWithCapturedOutput();
|
||||||
|
|
||||||
|
@ -24,11 +24,11 @@ namespace Microsoft.DotNet.Tools.Builder.Tests
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ErrorOccursWhenBuildingPortableProjectAndSpecifyingFrameworkThatProjectDoesNotSupport()
|
public void ErrorOccursWhenBuildingPortableProjectAndSpecifyingFrameworkThatProjectDoesNotSupport()
|
||||||
{
|
{
|
||||||
var testInstance = TestAssetsManager.CreateTestInstance("BuildTestPortableProject")
|
var testInstance = TestAssetsManager.CreateTestInstance("PortableTests")
|
||||||
.WithLockFiles();
|
.WithLockFiles();
|
||||||
|
|
||||||
var result = new BuildCommand(
|
var result = new BuildCommand(
|
||||||
projectPath: testInstance.TestRoot,
|
projectPath: Path.Combine(testInstance.TestRoot, "PortableApp"),
|
||||||
output: Path.Combine(testInstance.TestRoot, "out"),
|
output: Path.Combine(testInstance.TestRoot, "out"),
|
||||||
framework: "sl40")
|
framework: "sl40")
|
||||||
.ExecuteWithCapturedOutput();
|
.ExecuteWithCapturedOutput();
|
||||||
|
@ -40,11 +40,11 @@ namespace Microsoft.DotNet.Tools.Builder.Tests
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ErrorOccursWhenBuildingStandaloneProjectToSpecificOutputPathWithoutSpecifyingFramework()
|
public void ErrorOccursWhenBuildingStandaloneProjectToSpecificOutputPathWithoutSpecifyingFramework()
|
||||||
{
|
{
|
||||||
var testInstance = TestAssetsManager.CreateTestInstance("BuildTestStandaloneProject")
|
var testInstance = TestAssetsManager.CreateTestInstance("PortableTests")
|
||||||
.WithLockFiles();
|
.WithLockFiles();
|
||||||
|
|
||||||
var result = new BuildCommand(
|
var result = new BuildCommand(
|
||||||
projectPath: testInstance.TestRoot,
|
projectPath: Path.Combine(testInstance.TestRoot, "StandaloneApp"),
|
||||||
output: Path.Combine(testInstance.TestRoot, "out"))
|
output: Path.Combine(testInstance.TestRoot, "out"))
|
||||||
.ExecuteWithCapturedOutput();
|
.ExecuteWithCapturedOutput();
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ namespace Microsoft.DotNet.Tools.Builder.Tests
|
||||||
private readonly string[] _libCompileFiles =
|
private readonly string[] _libCompileFiles =
|
||||||
{
|
{
|
||||||
"TestLibrary" + FileNameSuffixes.DotNet.DynamicLib,
|
"TestLibrary" + FileNameSuffixes.DotNet.DynamicLib,
|
||||||
"TestLibrary" + FileNameSuffixes.DotNet.ProgramDatabase,
|
"TestLibrary" + FileNameSuffixes.DotNet.ProgramDatabase
|
||||||
};
|
};
|
||||||
|
|
||||||
private void GetProjectInfo(string testRoot)
|
private void GetProjectInfo(string testRoot)
|
||||||
|
|
|
@ -9,28 +9,27 @@ namespace Microsoft.DotNet.Tools.Builder.Tests
|
||||||
[Fact]
|
[Fact]
|
||||||
public void BuildingAPortableProjectProducesDepsFile()
|
public void BuildingAPortableProjectProducesDepsFile()
|
||||||
{
|
{
|
||||||
var testInstance = TestAssetsManager.CreateTestInstance("BuildTestPortableProject")
|
var testInstance = TestAssetsManager.CreateTestInstance("PortableTests")
|
||||||
.WithLockFiles();
|
.WithLockFiles();
|
||||||
|
|
||||||
var result = new BuildCommand(
|
var result = new BuildCommand(
|
||||||
projectPath: testInstance.TestRoot,
|
projectPath: Path.Combine(testInstance.TestRoot, "PortableApp"))
|
||||||
forcePortable: true)
|
|
||||||
.ExecuteWithCapturedOutput();
|
.ExecuteWithCapturedOutput();
|
||||||
|
|
||||||
result.Should().Pass();
|
result.Should().Pass();
|
||||||
|
|
||||||
var outputBase = new DirectoryInfo(Path.Combine(testInstance.TestRoot, "bin", "Debug"));
|
var outputBase = new DirectoryInfo(Path.Combine(testInstance.TestRoot, "PortableApp", "bin", "Debug"));
|
||||||
|
|
||||||
var netstandardappOutput = outputBase.Sub("netstandardapp1.5");
|
var netstandardappOutput = outputBase.Sub("netstandard1.5");
|
||||||
|
|
||||||
netstandardappOutput.Should()
|
netstandardappOutput.Should()
|
||||||
.Exist().And
|
.Exist().And
|
||||||
.HaveFiles(new[]
|
.HaveFiles(new[]
|
||||||
{
|
{
|
||||||
"BuildTestPortableProject.deps",
|
"PortableApp.deps",
|
||||||
"BuildTestPortableProject.deps.json",
|
"PortableApp.deps.json",
|
||||||
"BuildTestPortableProject.dll",
|
"PortableApp.dll",
|
||||||
"BuildTestPortableProject.pdb"
|
"PortableApp.pdb"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
54
test/dotnet-publish.Tests/PublishPortableTests.cs
Normal file
54
test/dotnet-publish.Tests/PublishPortableTests.cs
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
using Microsoft.DotNet.Tools.Test.Utilities;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.DotNet.Tools.Publish.Tests
|
||||||
|
{
|
||||||
|
public class PublishPortableTests : TestBase
|
||||||
|
{
|
||||||
|
private static readonly IEnumerable<Tuple<string, string>> ExpectedRuntimeOutputs = new[] {
|
||||||
|
Tuple.Create("debian-x64", "libuv.so"),
|
||||||
|
Tuple.Create("rhel-x64", "libuv.so"),
|
||||||
|
Tuple.Create("osx", "libuv.dylib"),
|
||||||
|
Tuple.Create("win7-arm", "libuv.dll"),
|
||||||
|
Tuple.Create("win7-x86", "libuv.dll"),
|
||||||
|
Tuple.Create("win7-x64", "libuv.dll")
|
||||||
|
};
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void PortableAppWithRuntimeTargetsIsPublishedCorrectly()
|
||||||
|
{
|
||||||
|
var testInstance = TestAssetsManager.CreateTestInstance("PortableTests")
|
||||||
|
.WithLockFiles();
|
||||||
|
|
||||||
|
var publishCommand = new PublishCommand(Path.Combine(testInstance.TestRoot, "PortableAppWithNative"));
|
||||||
|
var publishResult = publishCommand.Execute();
|
||||||
|
|
||||||
|
publishResult.Should().Pass();
|
||||||
|
|
||||||
|
var publishDir = publishCommand.GetOutputDirectory(portable: true);
|
||||||
|
publishDir.Should().HaveFiles(new[]
|
||||||
|
{
|
||||||
|
"PortableAppWithNative.dll",
|
||||||
|
"PortableAppWithNative.deps",
|
||||||
|
"PortableAppWithNative.deps.json"
|
||||||
|
});
|
||||||
|
|
||||||
|
var runtimesOutput = publishDir.Sub("runtimes");
|
||||||
|
|
||||||
|
runtimesOutput.Should().Exist();
|
||||||
|
|
||||||
|
foreach (var output in ExpectedRuntimeOutputs)
|
||||||
|
{
|
||||||
|
var ridDir = runtimesOutput.Sub(output.Item1);
|
||||||
|
ridDir.Should().Exist();
|
||||||
|
|
||||||
|
var nativeDir = ridDir.Sub("native");
|
||||||
|
nativeDir.Should().Exist();
|
||||||
|
nativeDir.Should().HaveFile(output.Item2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue