- Make all of the code looking for built assets use the OutputPathCalculator

- Project dependencies are always built into their specific folders and the main project is the only one that uses the output path and intermediate output path variable.
- Publish respects the output path for publish only, not compile as part of publish. This means that publishing multiple runtimes will stomp on each other. So don't do that. We can throw if you specify and output location and you haven't specified a specific combination of RID and framework. Alternatively it should probably just pick the first TFM/RID pair from the lock file. This is similar to how `dotnet run` works.
- Cleaned up the incremental build output formatting
- Use a single stream (output stream) since interleaving them was causing formatting issues (like losing random characters in the middle of outputting things).
- Didn't change how pack works, it still preserves the output structure when passing `--output`, this one is worth discussing. We could leave the build output inplace and only move the package to the output location. That's more consistent with how everything else works and can be a follow up PR.
This commit is contained in:
David Fowler 2016-01-26 06:39:13 -08:00
parent 788194e48e
commit a35ae177ff
22 changed files with 190 additions and 174 deletions

View file

@ -9,7 +9,6 @@ $TestPackagesPath = "$RepoRoot\tests\packages"
$ArgTestRoot = "$RepoRoot\test\ArgumentForwardingTests"
$ArgTestOutputRoot = "$RepoRoot\artifacts\tests\arg-forwarding"
$ArgTestBin = "$ArgTestOutputRoot\$Configuration\dnxcore50"
dotnet publish --framework "dnxcore50" --runtime "$Rid" --output "$ArgTestOutputRoot" --configuration "$Configuration" "$ArgTestRoot\Reflector"
if (!$?) {
@ -23,9 +22,9 @@ if (!$?) {
Exit 1
}
cp "$ArgTestRoot\Reflector\reflector_cmd.cmd" "$ArgTestBin"
cp "$ArgTestRoot\Reflector\reflector_cmd.cmd" "$ArgTestOutputRoot"
pushd "$ArgTestBin"
pushd "$ArgTestOutputRoot"
& ".\corerun" "xunit.console.netcore.exe" "ArgumentForwardingTests.dll" -xml "$_-testResults.xml" -notrait category=failing
$exitCode = $LastExitCode

View file

@ -19,13 +19,12 @@ source "$DIR/../common/_common.sh"
ArgTestRoot="$REPOROOT/test/ArgumentForwardingTests"
ArgTestOutputRoot="$REPOROOT/artifacts/tests/arg-forwarding"
ArgTestBin="$ArgTestOutputRoot/$CONFIGURATION/dnxcore50"
dotnet publish --framework "dnxcore50" --output "$ArgTestOutputRoot" --configuration "$CONFIGURATION" "$ArgTestRoot/Reflector"
dotnet publish --framework "dnxcore50" --output "$ArgTestOutputRoot" --configuration "$CONFIGURATION" "$ArgTestRoot/ArgumentForwardingTests"
pushd "$ArgTestBin"
pushd "$ArgTestOutputRoot"
./corerun "xunit.console.netcore.exe" "ArgumentForwardingTests.dll" -xml "ArgumentForwardingTests-testResults.xml" -notrait category=failing
popd

View file

@ -207,7 +207,7 @@ namespace Microsoft.DotNet.Cli.Utils
private static string GetDepsPath(ProjectContext context, string buildConfiguration)
{
return Path.Combine(context.GetOutputDirectoryPath(buildConfiguration),
return Path.Combine(context.GetOutputPathCalculator().GetOutputDirectoryPath(buildConfiguration),
context.ProjectFile.Name + FileNameSuffixes.Deps);
}

View file

@ -20,8 +20,8 @@ namespace Microsoft.DotNet.Cli.Utils
}
public static Reporter Output { get; } = Create(AnsiConsole.GetOutput);
public static Reporter Error { get; } = Create(AnsiConsole.GetError);
public static Reporter Verbose { get; } = CommandContext.IsVerbose() ? Create(AnsiConsole.GetError) : Null;
public static Reporter Error { get; } = Create(AnsiConsole.GetOutput);
public static Reporter Verbose { get; } = CommandContext.IsVerbose() ? Create(AnsiConsole.GetOutput) : Null;
public static Reporter Create(Func<bool, AnsiConsole> getter)
{

View file

@ -1,22 +1,12 @@
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
{
public 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);
}
public static void WriteDepsTo(this IEnumerable<LibraryExport> exports, string path)
{
File.WriteAllLines(path, exports.SelectMany(GenerateLines));

View file

@ -19,6 +19,7 @@ namespace Microsoft.DotNet.Cli.Compiler.Common
public static class ProjectContextExtensions
{
public static string ProjectName(this ProjectContext context) => context.RootProject.Identity.Name;
public static string GetDisplayName(this ProjectContext context) => $"{context.RootProject.Identity.Name} ({context.TargetFramework})";
public static void MakeCompilationOutputRunnable(this ProjectContext context, string outputPath, string configuration)
{

View file

@ -37,7 +37,7 @@ namespace Microsoft.DotNet.ProjectModel.Loader
dllImports,
// Add the project's output directory path to ensure project-to-project references get located
new[] { context.GetOutputDirectoryPath(configuration) });
new[] { context.GetOutputPathCalculator().GetOutputDirectoryPath(configuration) });
}
}
}

View file

@ -163,6 +163,11 @@ namespace Microsoft.DotNet.ProjectModel.Compilation
assemblyPath,
Path.Combine(project.Project.ProjectDirectory, assemblyPath)));
}
else
{
var assemblyPath = project.GetOutputPathCalculator().GetAssemblyPath(_configuration);
compileAssemblies.Add(new LibraryAsset(project.Identity.Name, null, assemblyPath));
}
// Add shared sources
foreach (var sharedFile in project.Project.Files.SharedFiles)

View file

@ -2,6 +2,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.IO;
using System.Runtime.InteropServices;
using NuGet.Frameworks;
namespace Microsoft.DotNet.ProjectModel
@ -10,7 +11,10 @@ namespace Microsoft.DotNet.ProjectModel
{
private const string ObjDirectoryName = "obj";
private readonly ProjectContext _project;
private readonly Project _project;
private readonly NuGetFramework _framework;
private readonly string _runtimeIdentifier;
/// <summary>
/// Unaltered output path. Either what is passed in in the constructor, or the project directory.
@ -20,10 +24,14 @@ namespace Microsoft.DotNet.ProjectModel
public string BaseCompilationOutputPath { get; }
public OutputPathCalculator(
ProjectContext project,
Project project,
NuGetFramework framework,
string runtimeIdentifier,
string baseOutputPath)
{
_project = project;
_framework = framework;
_runtimeIdentifier = runtimeIdentifier;
BaseOutputPath = string.IsNullOrWhiteSpace(baseOutputPath) ? _project.ProjectDirectory : baseOutputPath;
@ -32,17 +40,21 @@ namespace Microsoft.DotNet.ProjectModel
: baseOutputPath;
}
public string GetCompilationOutputPath(string buildConfiguration)
public string GetOutputDirectoryPath(string buildConfiguration)
{
var outDir = Path.Combine(
BaseCompilationOutputPath,
var outDir = Path.Combine(BaseCompilationOutputPath,
buildConfiguration,
_project.TargetFramework.GetTwoDigitShortFolderName());
_framework.GetShortFolderName());
if (!string.IsNullOrEmpty(_runtimeIdentifier))
{
outDir = Path.Combine(outDir, _runtimeIdentifier);
}
return outDir;
}
public string GetIntermediateOutputPath(string buildConfiguration, string intermediateOutputValue)
public string GetIntermediateOutputDirectoryPath(string buildConfiguration, string intermediateOutputValue)
{
string intermediateOutputPath;
@ -52,7 +64,7 @@ namespace Microsoft.DotNet.ProjectModel
BaseOutputPath,
ObjDirectoryName,
buildConfiguration,
_project.TargetFramework.GetTwoDigitShortFolderName());
_framework.GetTwoDigitShortFolderName());
}
else
{
@ -61,5 +73,43 @@ namespace Microsoft.DotNet.ProjectModel
return intermediateOutputPath;
}
public string GetAssemblyPath(string buildConfiguration)
{
var compilationOptions = _project.GetCompilerOptions(_framework, buildConfiguration);
var outputExtension = FileNameSuffixes.DotNet.DynamicLib;
if (_framework.IsDesktop() && compilationOptions.EmitEntryPoint.GetValueOrDefault())
{
outputExtension = FileNameSuffixes.DotNet.Exe;
}
return Path.Combine(
GetOutputDirectoryPath(buildConfiguration),
_project.Name + outputExtension);
}
public string GetExecutablePath(string buildConfiguration)
{
var extension = FileNameSuffixes.CurrentPlatform.Exe;
// This is the check for mono, if we're not on windows and producing outputs for
// the desktop framework then it's an exe
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && _framework.IsDesktop())
{
extension = FileNameSuffixes.DotNet.Exe;
}
return Path.Combine(
GetOutputDirectoryPath(buildConfiguration),
_project.Name + extension);
}
public string GetPdbPath(string buildConfiguration)
{
return Path.Combine(
GetOutputDirectoryPath(buildConfiguration),
_project.Name + FileNameSuffixes.DotNet.ProgramDatabase);
}
}
}

View file

@ -120,37 +120,9 @@ namespace Microsoft.DotNet.ProjectModel
.BuildAllTargets();
}
public string GetAssemblyPath(string buildConfiguration)
public OutputPathCalculator GetOutputPathCalculator(string baseOutputPath = null)
{
return Path.Combine(
GetOutputDirectoryPath(buildConfiguration),
ProjectFile.Name + FileNameSuffixes.DotNet.DynamicLib);
}
public string GetPdbPath(string buildConfiguration)
{
return Path.Combine(
GetOutputDirectoryPath(buildConfiguration),
ProjectFile.Name + FileNameSuffixes.DotNet.ProgramDatabase);
}
public string GetOutputDirectoryPath(string buildConfiguration)
{
var outDir = Path.Combine(
ProjectDirectory,
DirectoryNames.Bin,
buildConfiguration,
TargetFramework.GetShortFolderName());
if (!string.IsNullOrEmpty(RuntimeIdentifier))
{
outDir = Path.Combine(outDir, RuntimeIdentifier);
}
return outDir;
}
public OutputPathCalculator GetOutputPathCalculator(string rootOutputPath)
{
return new OutputPathCalculator(this, rootOutputPath);
return new OutputPathCalculator(ProjectFile, TargetFramework, RuntimeIdentifier, baseOutputPath);
}
}
}

View file

@ -43,5 +43,10 @@ namespace Microsoft.DotNet.ProjectModel
public Project Project { get; }
public TargetFrameworkInformation TargetFrameworkInfo { get; }
public OutputPathCalculator GetOutputPathCalculator()
{
return new OutputPathCalculator(Project, Framework, runtimeIdentifier: null, baseOutputPath: null);
}
}
}

View file

@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
@ -20,7 +19,6 @@ namespace Microsoft.DotNet.Tools.Build
// Collects icnremental safety checks and transitively compiles a project context
internal class CompileContext
{
public static readonly string[] KnownCompilers = { "csc", "vbc", "fsc" };
private readonly ProjectContext _rootProject;
@ -36,13 +34,13 @@ namespace Microsoft.DotNet.Tools.Build
// Cleaner to clone the args and mutate the clone than have separate CompileContext fields for mutated args
// and then reasoning which ones to get from args and which ones from fields.
_args = (BuilderCommandApp) args.ShallowCopy();
_args = (BuilderCommandApp)args.ShallowCopy();
// Set up Output Paths. They are unique per each CompileContext
var outputPathCalculator = _rootProject.GetOutputPathCalculator(_args.OutputValue);
_args.OutputValue = outputPathCalculator.BaseCompilationOutputPath;
_args.IntermediateValue =
outputPathCalculator.GetIntermediateOutputPath(_args.ConfigValue, _args.IntermediateValue);
outputPathCalculator.GetIntermediateOutputDirectoryPath(_args.ConfigValue, _args.IntermediateValue);
// Set up dependencies
_dependencies = new ProjectDependenciesFacade(_rootProject, _args.ConfigValue);
@ -62,7 +60,7 @@ namespace Microsoft.DotNet.Tools.Build
{
var dependencyProjectContext = ProjectContext.Create(dependency.Path, dependency.Framework);
if (!NeedsRebuilding(dependencyProjectContext, new ProjectDependenciesFacade(dependencyProjectContext, _args.ConfigValue)))
if (!DependencyNeedsRebuilding(dependencyProjectContext, new ProjectDependenciesFacade(dependencyProjectContext, _args.ConfigValue)))
{
continue;
}
@ -88,14 +86,24 @@ namespace Microsoft.DotNet.Tools.Build
return success;
}
private bool DependencyNeedsRebuilding(ProjectContext project, ProjectDependenciesFacade dependencies)
{
return NeedsRebuilding(project, dependencies, buildOutputPath: null, intermediateOutputPath: null);
}
private bool NeedsRebuilding(ProjectContext project, ProjectDependenciesFacade dependencies)
{
var compilerIO = GetCompileIO(project, _args.ConfigValue, _args.OutputValue, _args.IntermediateValue, dependencies);
return NeedsRebuilding(project, dependencies, _args.OutputValue, _args.IntermediateValue);
}
private bool NeedsRebuilding(ProjectContext project, ProjectDependenciesFacade dependencies, string buildOutputPath, string intermediateOutputPath)
{
var compilerIO = GetCompileIO(project, _args.ConfigValue, buildOutputPath, intermediateOutputPath, dependencies);
// rebuild if empty inputs / outputs
if (!(compilerIO.Outputs.Any() && compilerIO.Inputs.Any()))
{
Reporter.Output.WriteLine($"\nProject {project.ProjectName()} will be compiled because it either has empty inputs or outputs");
Reporter.Output.WriteLine($"Project {project.GetDisplayName()} will be compiled because it either has empty inputs or outputs");
return true;
}
@ -125,19 +133,25 @@ namespace Microsoft.DotNet.Tools.Build
if (!newInputs.Any())
{
Reporter.Output.WriteLine($"\nProject {project.ProjectName()} was previously compiled. Skipping compilation.");
Reporter.Output.WriteLine($"Project {project.GetDisplayName()} was previously compiled. Skipping compilation.");
return false;
}
Reporter.Output.WriteLine($"\nProject {project.ProjectName()} will be compiled because some of its inputs were newer than its oldest output.");
Reporter.Verbose.WriteLine($"Oldest output item was written at {minDate} : {minOutputPath}");
Reporter.Verbose.WriteLine($"Inputs newer than the oldest output item:");
Reporter.Output.WriteLine($"Project {project.GetDisplayName()} will be compiled because some of its inputs were newer than its oldest output.");
Reporter.Verbose.WriteLine();
Reporter.Verbose.WriteLine($" Oldest output item:");
Reporter.Verbose.WriteLine($" {minDate}: {minOutputPath}");
Reporter.Verbose.WriteLine();
Reporter.Verbose.WriteLine($" Inputs newer than the oldest output item:");
foreach (var newInput in newInputs)
{
Reporter.Verbose.WriteLine($"\t{File.GetLastWriteTime(newInput)}\t:\t{newInput}");
Reporter.Verbose.WriteLine($" {File.GetLastWriteTime(newInput)}: {newInput}");
}
Reporter.Verbose.WriteLine();
return true;
}
@ -150,14 +164,14 @@ namespace Microsoft.DotNet.Tools.Build
return false;
}
Reporter.Output.WriteLine($"\nProject {project.ProjectName()} will be compiled because expected {itemsType} are missing. ");
Reporter.Verbose.WriteLine($"Project {project.GetDisplayName()} will be compiled because expected {itemsType} are missing.");
foreach (var missing in missingItems)
{
Reporter.Verbose.WriteLine($"\t {missing}");
Reporter.Verbose.WriteLine($" {missing}");
}
Reporter.Output.WriteLine();
Reporter.Verbose.WriteLine(); ;
return true;
}
@ -205,7 +219,7 @@ namespace Microsoft.DotNet.Tools.Build
private List<ProjectContext> GetProjectsToCheck()
{
// include initial root project
var contextsToCheck = new List<ProjectContext>(1 + _dependencies.ProjectDependenciesWithSources.Count) {_rootProject};
var contextsToCheck = new List<ProjectContext>(1 + _dependencies.ProjectDependenciesWithSources.Count) { _rootProject };
// convert ProjectDescription to ProjectContext
var dependencyContexts = _dependencies.ProjectDependenciesWithSources.Select
@ -262,12 +276,8 @@ namespace Microsoft.DotNet.Tools.Build
args.Add("--framework");
args.Add($"{projectDependency.Framework}");
args.Add("--configuration");
args.Add($"{_args.ConfigValue}");
args.Add("--output");
args.Add($"{_args.OutputValue}");
args.Add("--temp-output");
args.Add($"{_args.IntermediateValue}");
args.Add($"{projectDependency.Project.ProjectDirectory}");
args.Add(_args.ConfigValue);
args.Add(projectDependency.Project.ProjectDirectory);
if (_args.NoHostValue)
{
@ -295,20 +305,20 @@ namespace Microsoft.DotNet.Tools.Build
args.Add("--temp-output");
args.Add(_args.IntermediateValue);
if (_args.NoHostValue)
{
args.Add("--no-host");
if (_args.NoHostValue)
{
args.Add("--no-host");
}
//native args
if (_args.IsNativeValue)
{
args.Add("--native");
if (_args.IsNativeValue)
{
args.Add("--native");
}
if (_args.IsCppModeValue)
{
args.Add("--cpp");
if (_args.IsCppModeValue)
{
args.Add("--cpp");
}
if (!string.IsNullOrWhiteSpace(_args.ArchValue))
@ -337,7 +347,7 @@ namespace Microsoft.DotNet.Tools.Build
args.Add(_rootProject.ProjectDirectory);
var compileResult = Command.Create("dotnet-compile",args)
var compileResult = Command.Create("dotnet-compile", args)
.ForwardStdOut()
.ForwardStdErr()
.Execute();
@ -387,11 +397,17 @@ namespace Microsoft.DotNet.Tools.Build
// computes all the inputs and outputs that would be used in the compilation of a project
// ensures that all paths are files
// ensures no missing inputs
public static CompilerIO GetCompileIO(ProjectContext project, string config, string outputPath, string intermediaryOutputPath, ProjectDependenciesFacade dependencies)
public static CompilerIO GetCompileIO(
ProjectContext project,
string buildConfiguration,
string outputPath,
string intermediaryOutputPath,
ProjectDependenciesFacade dependencies)
{
var compilerIO = new CompilerIO(new List<string>(), new List<string>());
var binariesOutputPath = project.GetOutputPathCalculator(outputPath).GetCompilationOutputPath(config);
var compilationOutput = CompilerUtil.GetCompilationOutput(project.ProjectFile, project.TargetFramework, config, binariesOutputPath);
var calculator = project.GetOutputPathCalculator(outputPath);
var binariesOutputPath = calculator.GetOutputDirectoryPath(buildConfiguration);
var compilationOutput = calculator.GetAssemblyPath(buildConfiguration);
// input: project.json
compilerIO.Inputs.Add(project.ProjectFile.ProjectFilePath);
@ -410,7 +426,7 @@ namespace Microsoft.DotNet.Tools.Build
compilerIO.Outputs.Add(compilationOutput);
// input / output: compilation options files
AddFilesFromCompilationOptions(project, config, compilationOutput, compilerIO);
AddFilesFromCompilationOptions(project, buildConfiguration, compilationOutput, compilerIO);
// input / output: resources without culture
AddCultureResources(project, intermediaryOutputPath, compilerIO);
@ -423,7 +439,7 @@ namespace Microsoft.DotNet.Tools.Build
private static void AddLockFile(ProjectContext project, CompilerIO compilerIO)
{
if(project.LockFile == null)
if (project.LockFile == null)
{
var errorMessage = $"Project {project.ProjectName()} does not have a lock file.";
Reporter.Error.WriteLine(errorMessage);

View file

@ -125,20 +125,6 @@ namespace Microsoft.DotNet.Tools.Compiler
// used in incremental compilation
public static IEnumerable<string> GetCompilationSources(ProjectContext project) => project.ProjectFile.Files.SourceFiles;
// used in incremental compilation
public static string GetCompilationOutput(Project project, NuGetFramework framework, string configuration, string outputPath)
{
var compilationOptions = project.GetCompilerOptions(framework, configuration);
var outputExtension = ".dll";
if (framework.IsDesktop() && compilationOptions.EmitEntryPoint.GetValueOrDefault())
{
outputExtension = ".exe";
}
return Path.Combine(outputPath, project.Name + outputExtension);
}
// used in incremental compilation for the key file
public static CommonCompilerOptions ResolveCompilationOptions(ProjectContext context, string configuration)
{

View file

@ -61,17 +61,16 @@ namespace Microsoft.DotNet.Tools.Compiler
CompilerCommandApp args)
{
var outputPathCalculator = context.GetOutputPathCalculator(args.OutputValue);
var outputPath = outputPathCalculator.GetCompilationOutputPath(args.ConfigValue);
var outputPath = outputPathCalculator.GetOutputDirectoryPath(args.ConfigValue);
var nativeOutputPath = Path.Combine(outputPath, "native");
var intermediateOutputPath =
outputPathCalculator.GetIntermediateOutputPath(args.ConfigValue, args.IntermediateValue);
outputPathCalculator.GetIntermediateOutputDirectoryPath(args.ConfigValue, args.IntermediateValue);
var nativeIntermediateOutputPath = Path.Combine(intermediateOutputPath, "native");
Directory.CreateDirectory(nativeOutputPath);
Directory.CreateDirectory(nativeIntermediateOutputPath);
var compilationOptions = context.ProjectFile.GetCompilerOptions(context.TargetFramework, args.ConfigValue);
var managedOutput =
CompilerUtil.GetCompilationOutput(context.ProjectFile, context.TargetFramework, args.ConfigValue, outputPath);
var managedOutput = outputPathCalculator.GetAssemblyPath(args.ConfigValue);
var nativeArgs = new List<string>();
@ -161,9 +160,9 @@ namespace Microsoft.DotNet.Tools.Compiler
{
// Set up Output Paths
var outputPathCalculator = context.GetOutputPathCalculator(args.OutputValue);
var outputPath = outputPathCalculator.GetCompilationOutputPath(args.ConfigValue);
var outputPath = outputPathCalculator.GetOutputDirectoryPath(args.ConfigValue);
var intermediateOutputPath =
outputPathCalculator.GetIntermediateOutputPath(args.ConfigValue, args.IntermediateValue);
outputPathCalculator.GetIntermediateOutputDirectoryPath(args.ConfigValue, args.IntermediateValue);
Directory.CreateDirectory(outputPath);
Directory.CreateDirectory(intermediateOutputPath);
@ -201,7 +200,7 @@ namespace Microsoft.DotNet.Tools.Compiler
}
// Get compilation options
var outputName = CompilerUtil.GetCompilationOutput(context.ProjectFile, context.TargetFramework, args.ConfigValue, outputPath);
var outputName = outputPathCalculator.GetAssemblyPath(args.ConfigValue);
// Assemble args
var compilerArgs = new List<string>()
@ -223,21 +222,7 @@ namespace Microsoft.DotNet.Tools.Compiler
foreach (var dependency in dependencies)
{
var projectDependency = dependency.Library as ProjectDescription;
if (projectDependency != null)
{
if (projectDependency.Project.Files.SourceFiles.Any())
{
var projectOutputPath = CompilerUtil.GetCompilationOutput(projectDependency.Project, projectDependency.Framework, args.ConfigValue, outputPath);
references.Add(projectOutputPath);
}
}
else
{
references.AddRange(dependency.CompilationAssemblies.Select(r => r.ResolvedPath));
}
references.AddRange(dependency.CompilationAssemblies.Select(r => r.ResolvedPath));
compilerArgs.AddRange(dependency.SourceReferences.Select(s => $"\"{s}\""));
// Add analyzer references
@ -289,7 +274,7 @@ namespace Microsoft.DotNet.Tools.Compiler
var compilerName = CompilerUtil.ResolveCompilerName(context);
// Write RSP file
var rsp = Path.Combine(intermediateOutputPath, $"dotnet-compile.{context.ProjectFile.Name}.rsp");
var rsp = Path.Combine(intermediateOutputPath, $"dotnet-compile.rsp");
File.WriteAllLines(rsp, compilerArgs);
// Run pre-compile event

View file

@ -77,39 +77,39 @@ namespace Microsoft.DotNet.Tools.Publish
/// <param name="configuration">Debug or Release</param>
/// <param name="nativeSubdirectories"></param>
/// <returns>Return 0 if successful else return non-zero</returns>
private static bool PublishProjectContext(ProjectContext context, string baseOutputPath, string configuration, bool nativeSubdirectories)
private static bool PublishProjectContext(ProjectContext context, string outputPath, string configuration, bool nativeSubdirectories)
{
Reporter.Output.WriteLine($"Publishing {context.RootProject.Identity.Name.Yellow()} for {context.TargetFramework.DotNetFrameworkName.Yellow()}/{context.RuntimeIdentifier.Yellow()}");
var options = context.ProjectFile.GetCompilerOptions(context.TargetFramework, configuration);
var outputPathCalculator = context.GetOutputPathCalculator(baseOutputPath);
var outputPath = outputPathCalculator.GetCompilationOutputPath(configuration);
if (string.IsNullOrEmpty(outputPath))
{
outputPath = context.GetOutputPathCalculator().GetOutputDirectoryPath(configuration);
}
var contextVariables = new Dictionary<string, string>
{
{ "publish:ProjectPath", context.ProjectDirectory },
{ "publish:Configuration", configuration },
{ "publish:OutputPath", outputPath },
{ "publish:PublishOutputPath", outputPathCalculator.BaseCompilationOutputPath },
{ "publish:Framework", context.TargetFramework.Framework },
{ "publish:Runtime", context.RuntimeIdentifier },
};
RunScripts(context, ScriptNames.PrePublish, contextVariables);
if (!Directory.Exists(outputPathCalculator.BaseCompilationOutputPath))
if (!Directory.Exists(outputPath))
{
Directory.CreateDirectory(outputPathCalculator.BaseCompilationOutputPath);
Directory.CreateDirectory(outputPath);
}
// Compile the project (and transitively, all it's dependencies)
var result = Command.Create("dotnet-build",
var result = Command.Create("dotnet-build",
new string[] {
"--framework",
"--framework",
$"{context.TargetFramework.DotNetFrameworkName}",
"--output",
$"{outputPathCalculator.BaseCompilationOutputPath}",
"--configuration",
"--configuration",
$"{configuration}",
"--no-host",
$"{context.ProjectFile.ProjectDirectory}"
@ -128,15 +128,9 @@ namespace Microsoft.DotNet.Tools.Publish
foreach (var export in exporter.GetAllExports())
{
// Skip copying project references
if (export.Library is ProjectDescription)
{
continue;
}
Reporter.Verbose.WriteLine($"Publishing {export.Library.Identity.ToString().Green().Bold()} ...");
PublishFiles(export.RuntimeAssemblies, outputPath, false);
PublishFiles(export.RuntimeAssemblies, outputPath, nativeSubdirectories: false);
PublishFiles(export.NativeLibraries, outputPath, nativeSubdirectories);
}
@ -193,6 +187,14 @@ namespace Microsoft.DotNet.Tools.Publish
}
File.Copy(file.ResolvedPath, Path.Combine(destinationDirectory, Path.GetFileName(file.ResolvedPath)), overwrite: true);
// Copy pdbs
var pdbPath = Path.ChangeExtension(file.ResolvedPath, FileNameSuffixes.DotNet.ProgramDatabase);
if (File.Exists(pdbPath))
{
File.Copy(pdbPath, Path.Combine(destinationDirectory, Path.GetFileName(pdbPath)), overwrite: true);
}
}
}

View file

@ -112,15 +112,14 @@ namespace Microsoft.DotNet.Tools.Run
}
// Now launch the output and give it the results
var outputName = Path.Combine(
_context.GetOutputPathCalculator(tempDir).GetCompilationOutputPath(Configuration),
_context.ProjectFile.Name + Constants.ExeSuffix);
var outputName = _context.GetOutputPathCalculator(tempDir).GetExecutablePath(Configuration);
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
if (_context.TargetFramework.IsDesktop())
{
// Run mono if we're running a desktop target on non windows
_args.Insert(0, outputName + ".exe");
_args.Insert(0, outputName);
if (string.Equals(Configuration, "Debug", StringComparison.OrdinalIgnoreCase))
{

View file

@ -34,7 +34,7 @@ namespace Microsoft.DotNet.Tools.Test
var parentProcessIdOption = app.Option("--parentProcessId", "Used by IDEs to specify their process ID. Test will exit if the parent process does.", CommandOptionType.SingleValue);
var portOption = app.Option("--port", "Used by IDEs to specify a port number to listen for a connection.", CommandOptionType.SingleValue);
var projectPath = app.Argument("<PROJECT>", "The project to test, defaults to the current directory. Can be a path to a project.json or a project directory.");
app.OnExecute(() =>
{
try
@ -51,17 +51,17 @@ namespace Microsoft.DotNet.Tools.Test
RegisterForParentProcessExit(processId);
}
var projectContexts = CreateProjectContexts(projectPath.Value);
var projectContext = projectContexts.First();
var testRunner = projectContext.ProjectFile.TestRunner;
if (portOption.HasValue())
{
int port;
if (!Int32.TryParse(portOption.Value(), out port))
{
throw new InvalidOperationException($"{portOption.Value()} is not a valid port number.");
@ -92,7 +92,7 @@ namespace Microsoft.DotNet.Tools.Test
private static int RunConsole(ProjectContext projectContext, CommandLineApplication app, string testRunner)
{
var commandArgs = new List<string> {projectContext.GetAssemblyPath(Constants.DefaultConfiguration)};
var commandArgs = new List<string> { projectContext.GetOutputPathCalculator().GetAssemblyPath(Constants.DefaultConfiguration) };
commandArgs.AddRange(app.RemainingArguments);
return Command.Create($"{GetCommandName(testRunner)}", commandArgs, projectContext.TargetFramework)
@ -171,7 +171,7 @@ namespace Microsoft.DotNet.Tools.Test
{
TestHostTracing.Source.TraceInformation("Starting Discovery");
var commandArgs = new List<string> { projectContext.GetAssemblyPath(Constants.DefaultConfiguration) };
var commandArgs = new List<string> { projectContext.GetOutputPathCalculator().GetAssemblyPath(Constants.DefaultConfiguration) };
commandArgs.AddRange(new[]
{
@ -193,7 +193,7 @@ namespace Microsoft.DotNet.Tools.Test
{
TestHostTracing.Source.TraceInformation("Starting Execution");
var commandArgs = new List<string> { projectContext.GetAssemblyPath(Constants.DefaultConfiguration) };
var commandArgs = new List<string> { projectContext.GetOutputPathCalculator().GetAssemblyPath(Constants.DefaultConfiguration) };
commandArgs.AddRange(new[]
{
@ -230,7 +230,7 @@ namespace Microsoft.DotNet.Tools.Test
throw new InvalidOperationException(error);
}
private static void ExecuteRunnerCommand(string testRunner, ReportingChannel channel, List<string> commandArgs)
{
var result = Command.Create(GetCommandName(testRunner), commandArgs, new NuGetFramework("DNXCore", Version.Parse("5.0")))

View file

@ -166,7 +166,7 @@ namespace Microsoft.DotNet.Tests.EndToEnd
var publishCommand = new PublishCommand(TestProject, output: OutputDirectory);
publishCommand.Execute().Should().Pass();
TestOutputExecutable(OutputDirectory, publishCommand.GetOutputExecutable(), s_expectedOutput);
TestExecutable(OutputDirectory, publishCommand.GetOutputExecutable(), s_expectedOutput);
}
private void TestSetup()

View file

@ -75,12 +75,12 @@ namespace Microsoft.DotNet.Tools.Builder.Tests
protected static void AssertProjectSkipped(string skippedProject, CommandResult buildResult)
{
Assert.Contains($"Project {skippedProject} was previously compiled. Skipping compilation.", buildResult.StdOut, StringComparison.OrdinalIgnoreCase);
Assert.Contains($"Project {skippedProject} (DNXCore,Version=v5.0) was previously compiled. Skipping compilation.", buildResult.StdOut, StringComparison.OrdinalIgnoreCase);
}
protected static void AssertProjectCompiled(string rebuiltProject, CommandResult buildResult)
{
Assert.Contains($"Project {rebuiltProject} will be compiled", buildResult.StdOut, StringComparison.OrdinalIgnoreCase);
Assert.Contains($"Project {rebuiltProject} (DNXCore,Version=v5.0) will be compiled", buildResult.StdOut, StringComparison.OrdinalIgnoreCase);
}
protected string GetBinDirectory()

View file

@ -63,7 +63,7 @@ namespace Microsoft.DotNet.Tools.Builder.Tests
Assert.False(File.Exists(lockFile));
buildResult = BuildProject(expectBuildFailure : true);
Assert.Contains("does not have a lock file", buildResult.StdErr);
Assert.Contains("does not have a lock file", buildResult.StdOut);
}
[Fact(Skip="https://github.com/dotnet/cli/issues/980")]

View file

@ -61,8 +61,8 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
string framework = string.IsNullOrEmpty(_framework) ?
_project.GetTargetFrameworks().First().FrameworkName.GetShortFolderName() : _framework;
string runtime = string.IsNullOrEmpty(_runtime) ? PlatformServices.Default.Runtime.GetLegacyRestoreRuntimeIdentifier() : _runtime;
//TODO: add runtime back as soon as it gets propagated through the various commands.
string output = Path.Combine(config, framework);
string output = Path.Combine(config, framework, runtime);
return output;
}
@ -71,7 +71,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
{
if (!string.IsNullOrEmpty(_output))
{
return new DirectoryInfo(Path.Combine(_output, BuildRelativeOutputPath()));
return new DirectoryInfo(_output);
}
string output = Path.Combine(_project.ProjectDirectory, "bin", BuildRelativeOutputPath());

View file

@ -58,13 +58,11 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
string.Equals("on", val, StringComparison.OrdinalIgnoreCase));
}
protected void TestOutputExecutable(
string outputDir,
protected void TestExecutable(string outputDir,
string executableName,
string expectedOutput,
bool native = false)
string expectedOutput)
{
var executablePath = Path.Combine(GetCompilationOutputPath(outputDir, native), executableName);
var executablePath = Path.Combine(outputDir, executableName);
var executableCommand = new TestCommand(executablePath);
@ -72,7 +70,16 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
result.Should().HaveStdOut(expectedOutput);
result.Should().NotHaveStdErr();
result.Should().Pass();
result.Should().Pass();
}
protected void TestOutputExecutable(
string outputDir,
string executableName,
string expectedOutput,
bool native = false)
{
TestExecutable(GetCompilationOutputPath(outputDir, native), executableName, expectedOutput);
}
protected void TestNativeOutputExecutable(string outputDir, string executableName, string expectedOutput)