Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/Cli/dotnet/Commands/Run/CSharpCompilerCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,9 @@ public int Execute(out bool fallbackToNormalBuild)
// Process the response.
var exitCode = ProcessBuildResponse(responseTask.Result, out fallbackToNormalBuild);

// Copy from obj to bin.
if (BuildResultFile != null &&
// Copy from obj to bin only if the build succeeded.
if (exitCode == 0 &&
BuildResultFile != null &&
CSharpCommandLineParser.Default.Parse(CscArguments, BaseDirectory, sdkDirectory: null) is { OutputFileName: { } outputFileName } parsedArgs)
{
var objFile = new FileInfo(parsedArgs.GetOutputFilePath(outputFileName));
Expand Down
51 changes: 51 additions & 0 deletions test/dotnet.Tests/CommandTests/Run/RunFileTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3576,6 +3576,57 @@ public void CscOnly_AfterMSBuild_SpacesInPath()
Build(testInstance, BuildLevel.Csc, expectedOutput: "v2 Release", programFileName: programFileName);
}

/// <summary>
/// Testing optimization <see cref="CscOnly_AfterMSBuild"/>.
/// When compilation fails, the obj dll should not be copied to bin directory.
/// This prevents spurious errors if the dll file was not even produced by roslyn due to compilation errors.
/// </summary>
[Fact]
public void CscOnly_AfterMSBuild_CompilationFailure_NoCopyToBin()
{
var testInstance = _testAssetsManager.CreateTestDirectory(baseDirectory: OutOfTreeBaseDirectory);

// First, create a valid program and build it successfully
var programPath = Path.Join(testInstance.Path, "Program.cs");
var code = """
#:property PublishAot=false
Console.WriteLine("version 1");
""";
File.WriteAllText(programPath, code);

var artifactsDir = VirtualProjectBuildingCommand.GetArtifactsPath(programPath);
if (Directory.Exists(artifactsDir)) Directory.Delete(artifactsDir, recursive: true);

Build(testInstance, BuildLevel.All, expectedOutput: "version 1");

// Verify that the dlls were created
var objDll = Path.Join(artifactsDir, "obj", "debug", "Program.dll");
new FileInfo(objDll).Should().Exist();
var binDll = Path.Join(artifactsDir, "bin", "debug", "Program.dll");
new FileInfo(binDll).Should().Exist();

// Delete the dlls
File.Delete(objDll);
File.Delete(binDll);

// Write invalid code that causes compilation to fail
code = code.Replace(";", "");
File.WriteAllText(programPath, code);

// Try to build the invalid code
new DotnetCommand(Log, "run", "-bl", "Program.cs")
.WithWorkingDirectory(testInstance.Path)
.Execute()
.Should().Fail()
.And.HaveStdOutContaining(CliCommandStrings.NoBinaryLogBecauseRunningJustCsc)
// error CS1002: ; expected
.And.HaveStdOutContaining("error CS1002")
.And.HaveStdErrContaining(CliCommandStrings.RunCommandException);

new FileInfo(objDll).Should().NotExist();
new FileInfo(binDll).Should().NotExist();
}

/// <summary>
/// See <see cref="CscOnly_AfterMSBuild"/>.
/// </summary>
Expand Down
Loading