diff --git a/TestAssets/TestProjects/AppWithOutputAssemblyName/Program.cs b/TestAssets/TestProjects/AppWithOutputAssemblyName/Program.cs new file mode 100644 index 000000000..73c3dabba --- /dev/null +++ b/TestAssets/TestProjects/AppWithOutputAssemblyName/Program.cs @@ -0,0 +1,10 @@ +namespace AppWithOutputAssemblyName +{ + public class MyApp + { + public static void Main() + { + System.Console.WriteLine("Hello, World!"); + } + } +} \ No newline at end of file diff --git a/TestAssets/TestProjects/AppWithOutputAssemblyName/project.json b/TestAssets/TestProjects/AppWithOutputAssemblyName/project.json new file mode 100644 index 000000000..5881f34db --- /dev/null +++ b/TestAssets/TestProjects/AppWithOutputAssemblyName/project.json @@ -0,0 +1,15 @@ +{ + "compilationOptions": { + "outputName": "MyApp", + "emitEntryPoint": true, + "preserveCompilationContext": true + }, + "dependencies": { + "NETStandard.Library": "1.0.0-rc2-23901" + }, + "frameworks": { + "netstandardapp1.5": { + "imports": "dnxcore50" + } + } +} \ No newline at end of file diff --git a/TestAssets/TestProjects/TestAppWithContentPackage/project.json b/TestAssets/TestProjects/TestAppWithContentPackage/project.json index 6e9d2a179..c92de9622 100644 --- a/TestAssets/TestProjects/TestAppWithContentPackage/project.json +++ b/TestAssets/TestProjects/TestAppWithContentPackage/project.json @@ -1,7 +1,8 @@ { "version": "1.0.0-*", "compilationOptions": { - "emitEntryPoint": true + "emitEntryPoint": true, + "outputName": "AppWithContentPackage" }, "dependencies": { "NETStandard.Library": "1.5.0-rc2-23911", diff --git a/src/Microsoft.DotNet.Compiler.Common/Executable.cs b/src/Microsoft.DotNet.Compiler.Common/Executable.cs index 3fa63b148..6e3012833 100644 --- a/src/Microsoft.DotNet.Compiler.Common/Executable.cs +++ b/src/Microsoft.DotNet.Compiler.Common/Executable.cs @@ -28,14 +28,14 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common private readonly LibraryExporter _exporter; - private readonly string _configuration; - private readonly OutputPaths _outputPaths; private readonly string _runtimeOutputPath; private readonly string _intermediateOutputPath; + private readonly CommonCompilerOptions _compilerOptions; + public Executable(ProjectContext context, OutputPaths outputPaths, LibraryExporter exporter, string configuration) { _context = context; @@ -43,7 +43,7 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common _runtimeOutputPath = outputPaths.RuntimeOutputPath; _intermediateOutputPath = outputPaths.IntermediateOutputDirectoryPath; _exporter = exporter; - _configuration = configuration; + _compilerOptions = _context.ProjectFile.GetCompilerOptions(_context.TargetFramework, configuration); } public void MakeCompilationOutputRunnable() @@ -76,11 +76,11 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common { WriteDepsFileAndCopyProjectDependencies(_exporter); - var emitEntryPoint = _context.ProjectFile.GetCompilerOptions(_context.TargetFramework, _configuration).EmitEntryPoint ?? false; + var emitEntryPoint = _compilerOptions.EmitEntryPoint ?? false; if (emitEntryPoint && !string.IsNullOrEmpty(_context.RuntimeIdentifier)) { // TODO: Pick a host based on the RID - CoreHost.CopyTo(_runtimeOutputPath, _context.ProjectFile.Name + Constants.ExeSuffix); + CoreHost.CopyTo(_runtimeOutputPath, GetOutputName() + Constants.ExeSuffix); } } @@ -144,7 +144,9 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common runtimeOptions.Add("framework", framework); } - var runtimeConfigJsonFile = Path.Combine(_runtimeOutputPath, _context.ProjectFile.Name + FileNameSuffixes.RuntimeConfigJson); + var runtimeConfigJsonFile = + Path.Combine(_runtimeOutputPath, GetOutputName() + FileNameSuffixes.RuntimeConfigJson); + using (var writer = new JsonTextWriter(new StreamWriter(File.Create(runtimeConfigJsonFile)))) { writer.Formatting = Formatting.Indented; @@ -155,18 +157,18 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common public void WriteDeps(LibraryExporter exporter) { - var path = Path.Combine(_runtimeOutputPath, _context.ProjectFile.Name + FileNameSuffixes.Deps); - CreateDirectoryIfNotExists(path); - File.WriteAllLines(path, exporter + Directory.CreateDirectory(_runtimeOutputPath); + + var depsFilePath = Path.Combine(_runtimeOutputPath, GetOutputName() + FileNameSuffixes.Deps); + File.WriteAllLines(depsFilePath, exporter .GetDependencies(LibraryType.Package) .SelectMany(GenerateLines)); - var compilerOptions = _context.ResolveCompilationOptions(_configuration); - var includeCompile = compilerOptions.PreserveCompilationContext == true; + var includeCompile = _compilerOptions.PreserveCompilationContext == true; var exports = exporter.GetAllExports().ToArray(); var dependencyContext = new DependencyContextBuilder().Build( - compilerOptions: includeCompile ? compilerOptions : null, + compilerOptions: includeCompile ? _compilerOptions : null, compilationExports: includeCompile ? exports : null, runtimeExports: exports, portable: string.IsNullOrEmpty(_context.RuntimeIdentifier), @@ -174,8 +176,8 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common runtime: _context.RuntimeIdentifier ?? string.Empty); var writer = new DependencyContextWriter(); - var depsJsonFile = Path.Combine(_runtimeOutputPath, _context.ProjectFile.Name + FileNameSuffixes.DepsJson); - using (var fileStream = File.Create(depsJsonFile)) + var depsJsonFilePath = Path.Combine(_runtimeOutputPath, GetOutputName() + FileNameSuffixes.DepsJson); + using (var fileStream = File.Create(depsJsonFilePath)) { writer.Write(dependencyContext, fileStream); } @@ -210,11 +212,9 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common } } - - private static void CreateDirectoryIfNotExists(string path) + private string GetOutputName() { - var depsFile = new FileInfo(path); - depsFile.Directory.Create(); + return _compilerOptions.OutputName ?? _context.ProjectFile.Name; } private static IEnumerable GenerateLines(LibraryExport export) diff --git a/src/Microsoft.DotNet.ProjectModel/RuntimeOutputFiles.cs b/src/Microsoft.DotNet.ProjectModel/RuntimeOutputFiles.cs index 6368f173b..7b5f2b355 100644 --- a/src/Microsoft.DotNet.ProjectModel/RuntimeOutputFiles.cs +++ b/src/Microsoft.DotNet.ProjectModel/RuntimeOutputFiles.cs @@ -37,8 +37,12 @@ namespace Microsoft.DotNet.ProjectModel // The executable is a DLL in this case extension = FileNameSuffixes.DotNet.DynamicLib; } + + var compilationOptions = Project.GetCompilerOptions(Framework, Configuration); - return Path.Combine(BasePath, Project.Name + extension); + return Path.Combine( + BasePath, + (compilationOptions.OutputName ?? Project.Name) + extension); } } diff --git a/src/dotnet/commands/dotnet-build/CompileContext.cs b/src/dotnet/commands/dotnet-build/CompileContext.cs index 229c5af15..3ea00b371 100644 --- a/src/dotnet/commands/dotnet-build/CompileContext.cs +++ b/src/dotnet/commands/dotnet-build/CompileContext.cs @@ -438,7 +438,6 @@ namespace Microsoft.DotNet.Tools.Build CopyCompilationOutput(outputPaths); - var options = runtimeContext.ProjectFile.GetCompilerOptions(runtimeContext.TargetFramework, _args.ConfigValue); var executable = new Executable(runtimeContext, outputPaths, libraryExporter, _args.ConfigValue); executable.MakeCompilationOutputRunnable(); diff --git a/src/dotnet/commands/dotnet-compile/ManagedCompiler.cs b/src/dotnet/commands/dotnet-compile/ManagedCompiler.cs index 46b7d7cb1..0c883c260 100644 --- a/src/dotnet/commands/dotnet-compile/ManagedCompiler.cs +++ b/src/dotnet/commands/dotnet-compile/ManagedCompiler.cs @@ -96,7 +96,8 @@ namespace Microsoft.DotNet.Tools.Compiler foreach (var resourceFile in dependency.EmbeddedResources) { var transformedResource = resourceFile.GetTransformedFile(intermediateOutputPath); - var resourceName = ResourceManifestName.CreateManifestName(Path.GetFileName(resourceFile.ResolvedPath), context.ProjectFile.Name); + var resourceName = ResourceManifestName.CreateManifestName( + Path.GetFileName(resourceFile.ResolvedPath), compilationOptions.OutputName ?? context.ProjectFile.Name); compilerArgs.Add($"--resource:\"{transformedResource}\",{resourceName}"); } @@ -119,13 +120,14 @@ namespace Microsoft.DotNet.Tools.Compiler context.RuntimeIdentifier ?? string.Empty); var writer = new DependencyContextWriter(); - var depsJsonFile = Path.Combine(intermediateOutputPath, context.ProjectFile.Name + "dotnet-compile.deps.json"); + var depsJsonFile = Path.Combine(intermediateOutputPath, + (compilationOptions.OutputName ?? context.ProjectFile.Name) + "dotnet-compile.deps.json"); using (var fileStream = File.Create(depsJsonFile)) { writer.Write(dependencyContext, fileStream); } - compilerArgs.Add($"--resource:\"{depsJsonFile}\",{context.ProjectFile.Name}.deps.json"); + compilerArgs.Add($"--resource:\"{depsJsonFile}\",{compilationOptions.OutputName ?? context.ProjectFile.Name}.deps.json"); } if (!AddNonCultureResources(context.ProjectFile, compilerArgs, intermediateOutputPath)) diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/BuildCommand.cs b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/BuildCommand.cs index 693b32586..f2e7468e3 100644 --- a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/BuildCommand.cs +++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/BuildCommand.cs @@ -261,9 +261,12 @@ namespace Microsoft.DotNet.Tools.Test.Utilities public string GetOutputExecutableName() { - var result = _project.Name; - result += RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".exe" : ""; - return result; + return _project.Name + GetExecutableExtension(); + } + + public string GetExecutableExtension() + { + return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".exe" : ""; } private string BuildArgs() diff --git a/test/dotnet-compile.Tests/CompilerTests.cs b/test/dotnet-compile.Tests/CompilerTests.cs index b1cbb3f88..79afaa837 100644 --- a/test/dotnet-compile.Tests/CompilerTests.cs +++ b/test/dotnet-compile.Tests/CompilerTests.cs @@ -124,7 +124,7 @@ namespace Microsoft.DotNet.Tools.Compiler.Tests var result = buildCommand.ExecuteWithCapturedOutput(); result.Should().Pass(); - result = Command.Create(Path.Combine(outputDir, buildCommand.GetOutputExecutableName()), new string [0]) + result = Command.Create(Path.Combine(outputDir, "AppWithContentPackage" + buildCommand.GetExecutableExtension()), new string [0]) .CaptureStdErr() .CaptureStdOut() .Execute(); @@ -137,13 +137,13 @@ namespace Microsoft.DotNet.Tools.Compiler.Tests new DirectoryInfo(outputDir).Should() .HaveFile("config.xml"); // verify embedded resources - result.StdOut.Should().Contain("TestAppWithContentPackage.dnf.png"); - result.StdOut.Should().Contain("TestAppWithContentPackage.ui.png"); + result.StdOut.Should().Contain("AppWithContentPackage.dnf.png"); + result.StdOut.Should().Contain("AppWithContentPackage.ui.png"); // verify 'all' language files not included - result.StdOut.Should().NotContain("TestAppWithContentPackage.dnf_all.png"); - result.StdOut.Should().NotContain("TestAppWithContentPackage.ui_all.png"); + result.StdOut.Should().NotContain("AppWithContentPackage.dnf_all.png"); + result.StdOut.Should().NotContain("AppWithContentPackage.ui_all.png"); // verify classes - result.StdOut.Should().Contain("TestAppWithContentPackage.Foo"); + result.StdOut.Should().Contain("AppWithContentPackage.Foo"); result.StdOut.Should().Contain("MyNamespace.Util"); } @@ -168,7 +168,7 @@ namespace Microsoft.DotNet.Tools.Compiler.Tests } [Fact] - public void CanSetOutputAssemblyName() + public void CanSetOutputAssemblyNameForLibraries() { var testInstance = TestAssetsManager @@ -185,6 +185,26 @@ namespace Microsoft.DotNet.Tools.Compiler.Tests new DirectoryInfo(outputDir).Should().HaveFiles(new [] { "MyLibrary.dll" }); } + [Fact] + public void CanSetOutputAssemblyNameForApps() + { + var testInstance = + TestAssetsManager + .CreateTestInstance("AppWithOutputAssemblyName") + .WithLockFiles(); + + var root = testInstance.TestRoot; + var outputDir = Path.Combine(root, "bin"); + var testProject = ProjectUtils.GetProjectJson(root, "AppWithOutputAssemblyName"); + var buildCommand = new BuildCommand(testProject, output: outputDir, framework: DefaultFramework); + var result = buildCommand.ExecuteWithCapturedOutput(); + result.Should().Pass(); + + new DirectoryInfo(outputDir).Should().HaveFiles( + new [] { "MyApp.dll", "MyApp" + buildCommand.GetExecutableExtension(), + "MyApp.runtimeconfig.json", "MyApp.deps", "MyApp.deps.json" }); + } + private void CopyProjectToTempDir(string projectDir, TempDirectory tempDir) { // copy all the files to temp dir