Skip to content
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
0bae975
Bump Microsoft.Build to 18.7.1 and align System.* band to 10.0.8
JanProvaznik Jul 9, 2026
c5509d6
Mark ShowMessageForImplicitlySkipAnalyzers multithreadable; fix test …
JanProvaznik Jul 9, 2026
f39df64
migrate csc
OvesN Jul 14, 2026
b64e6b3
Remove redundant server environment clear
OvesN Jul 15, 2026
3ad846e
Merge branch 'main' into dev/veronikao/migrate-csc
OvesN Jul 27, 2026
0255db0
Require callers to explicitly provide environment lookup for runtime …
OvesN Jul 29, 2026
fb98f60
Pass explicit environment snapshots into BuildServerConnection instea…
OvesN Jul 29, 2026
ec9fe01
Merge branch 'main' of https://github.com/dotnet/roslyn into dev/vero…
OvesN Jul 29, 2026
c175fa7
Clean up, revert unnecessary changes
OvesN Jul 29, 2026
b941367
formatting
OvesN Jul 29, 2026
a15813d
Use BannedSymbols
jaredpar Jul 30, 2026
fab0b1c
fixes
jaredpar Jul 30, 2026
c533da2
fixes
jaredpar Jul 30, 2026
f3288fb
fixes
jaredpar Jul 30, 2026
bd3f2d0
new sdk
jaredpar Jul 30, 2026
1a92c26
Merge remote-tracking branch 'origin/features/msbuildmt' into fix-csc…
jaredpar Jul 30, 2026
9448129
fixes
jaredpar Jul 30, 2026
e47dd8c
new sdk version
jaredpar Jul 31, 2026
da0fc32
fixes
jaredpar Aug 4, 2026
80d8ad3
Merge origin/main into fix-csc-task
jaredpar Aug 11, 2026
5258959
PR feedback
jaredpar Aug 11, 2026
e2033b5
Pr feedback
jaredpar Aug 11, 2026
d282f14
more
jaredpar Aug 12, 2026
fa0cf21
more
jaredpar Aug 12, 2026
3ba8a2f
build error
jaredpar Aug 12, 2026
7b28515
Apply suggestion from @jjonescz
jaredpar Aug 13, 2026
dab569d
pr feedback
jaredpar Aug 13, 2026
2f7cafc
Fix MSBuild task path tests
jaredpar Aug 13, 2026
5fac7bd
Document multithreaded MSBuild task helpers
jaredpar Aug 13, 2026
52b773a
pr feedback
jaredpar Aug 14, 2026
305eb0c
Merge remote-tracking branch 'jaredpar/fix-csc-task' into fix-csc-task
jaredpar Aug 14, 2026
d29f6d5
pr feedback
jaredpar Aug 15, 2026
58b9fc3
Apply suggestion from @jaredpar
jaredpar Aug 17, 2026
6e0c557
fix
jaredpar Aug 17, 2026
f8ddfd6
fixes
jaredpar Aug 19, 2026
fd30eaf
more
jaredpar Aug 19, 2026
775c916
pr feedback
jaredpar Aug 19, 2026
259bfda
Move to interface instead of conditional code
jaredpar Aug 21, 2026
6e50163
PR Feedback
jaredpar Aug 25, 2026
ce86426
Fix empty temp path handling
jaredpar Aug 25, 2026
627bbdc
PR feedback
jaredpar Aug 25, 2026
3b1378e
more
jaredpar Aug 25, 2026
9feef99
more
jaredpar Aug 25, 2026
cb14d46
more
jaredpar Aug 25, 2026
77108f1
more
jaredpar Aug 26, 2026
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
6 changes: 6 additions & 0 deletions .github/instructions/Compiler.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ Compiler tasks are in `src/Compilers/Core/MSBuildTask/`:
- `Csc.cs` - C# compiler task
- `Vbc.cs` - VB compiler task
- `ManagedCompiler.cs` - Base compiler task functionality
- `Extensions.cs` - `TaskEnvironment`-based path and temporary-directory helpers
Comment thread
jaredpar marked this conversation as resolved.
Resolved

Multithreaded MSBuild tasks must read process-dependent state through their `TaskEnvironment`
rather than directly using `Environment`, `Directory`, or working-directory-sensitive `Path`
APIs. Shared compatibility helpers for environment and path behavior live under
`src/Compilers/Core/Portable/InternalUtilities/`.

## Performance Considerations

Expand Down
2 changes: 1 addition & 1 deletion .github/memory/FILE_MAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ This file is a **top-level map only**. For per-area directory detail, read the m

| Area | Layer | Purpose |
|------|-------|---------|
| `Compilers/` | compiler | C#/VB compilers (`Core`, `CSharp`, `VisualBasic`, `Server`). |
| `Compilers/` | compiler | C#/VB compilers (`Core`, including MSBuild tasks; `CSharp`; `VisualBasic`; `Server`). |
Comment thread
jaredpar marked this conversation as resolved.
Resolved
| `Dependencies/` | compiler | High-performance pooled collections & threading. |
| `ExpressionEvaluator/` | compiler | Debugger expression evaluator. |
| `Tools/` | compiler | Compiler tooling (BuildBoss, format tools) and benchmark harnesses. |
Expand Down
14 changes: 14 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,20 @@
"problemMatcher": "$msCompile",
"group": "build"
},
{
"label": "build Compilers.slnf with analyzers",
"command": "dotnet",
"type": "shell",
"args": [
"build",
"-p:RunAnalyzersDuringBuild=true",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we set /p:RoslynEnforceCodeStyle=true too?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was just following the other patterns in this file. Got to be honest ... I'm surprised that these are separate settings. I would assume that enabling analyzers turned on code style enforcement. Is that not the case?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why is that but I think they are separate. Our CI checks set both:

- script: ./eng/build.sh --solution Roslyn.slnx --restore --build --configuration Debug --prepareMachine --ci --binaryLog --runanalyzers --warnaserror /p:RoslynEnforceCodeStyle=true

"-p:GenerateFullPaths=true",
"-tl:off",
"Compilers.slnf"
],
"problemMatcher": "$msCompile",
"group": "build"
},
{
"label": "build Roslyn.slnx",
"command": "dotnet",
Expand Down
11 changes: 11 additions & 0 deletions src/Compilers/Core/MSBuildTask/BannedSymbols.MSBuildMT.txt
Comment thread
jaredpar marked this conversation as resolved.
Resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
P:System.Environment.CurrentDirectory
M:System.Environment.GetEnvironmentVariable(System.String);
M:System.Environment.GetEnvironmentVariables();
M:System.Environment.GetCommandLineArgs();
M:System.Environment.GetFolderPath();
M:System.Environment.GetLogicalDrives();
M:System.Environment.SetEnvironmentVariable();
M:System.IO.Directory.GetCurrentDirectory();
M:System.IO.Path.GetTempPath();
M:System.IO.Path.GetFullPath(System.String);
M:System.IO.Path.GetFullPath(System.String, System.String);
1 change: 1 addition & 0 deletions src/Compilers/Core/MSBuildTask/Csc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ namespace Microsoft.CodeAnalysis.BuildTasks
/// should be significantly faster with larger projects and have a smaller memory
/// footprint.
/// </summary>
[MSBuildMultiThreadableTask]
public class Csc : ManagedCompiler
{
#region Properties
Expand Down
2 changes: 2 additions & 0 deletions src/Compilers/Core/MSBuildTask/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
<Compile Include="$(MSBuildThisFileDirectory)CopyRefAssembly.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Csc.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Csi.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Extensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)GenerateMSBuildEditorConfig.cs" />
<Compile Include="$(MSBuildThisFileDirectory)IAnalyzerConfigFilesHostObject.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ICompilerOptionsHostObject.cs" />
Expand All @@ -59,6 +60,7 @@
<PackageCopyToOutput>true</PackageCopyToOutput>
<PackagePath>contentFiles\any\any</PackagePath>
</Content>
<AdditionalFiles Include="$(MSBuildThisFileDirectory)BannedSymbols.MSBuildMT.txt" />
</ItemGroup>

<Import Project="$(MSBuildThisFileDirectory)..\..\..\NuGet\Microsoft.CodeAnalysis.BuildClient.Package\Microsoft.CodeAnalysis.BuildClient.targets" />
Expand Down
91 changes: 91 additions & 0 deletions src/Compilers/Core/MSBuildTask/Extensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.Build.Framework;
using Microsoft.CodeAnalysis.BuildTasks;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CommandLine;

internal static class Extensions
{
extension(TaskEnvironment taskEnvironment)
{
internal string GetFullPath(string path)
{
var fullPath = taskEnvironment.GetAbsolutePath(path).Value;
return fullPath;
}

internal string GetFullPathNoThrow(string path)
{
try
{
path = taskEnvironment.GetFullPath(path);
}
catch (Exception e) when (Utilities.IsIoRelatedException(e)) { }
return path;
}

/// <summary>
/// Gets the value of the temporary path for the provided environment settings. This behavior
/// is OS specific.
/// - On Windows it seeks to emulate Path.GetTempPath as closely as possible with
/// provided working directory.
/// </summary>
internal string? GetTempPath()
{
return RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
? getTempPathWindows()
: getTempPathLinux();
Comment thread
jaredpar marked this conversation as resolved.
Resolved

string? getTempPathLinux()
{
// Unix temp path is fine: it does not use the working directory
// (it uses ${TMPDIR} if set, otherwise, it returns /tmp)
var tempPath = taskEnvironment.GetEnvironmentVariable("TMPDIR");
return !string.IsNullOrEmpty(tempPath) ? tempPath : "/tmp";
}

string? getTempPathWindows()
{
var tmp = taskEnvironment.GetEnvironmentVariable("TMP");
if (Path.IsPathRooted(tmp))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Path like \tmp is rooted but not fully qualified, so it can still depend on the current working directory.

@jaredpar jaredpar Aug 17, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch ... have a few places I need to fix this. I think that I need to keep the IsPathRooted check here cause that is how GetTempPathW works but I need to qualify with current project directory.

@baronfel FYI ... more weirdness on replacing GetTempPath

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Path like \tmp is rooted but not fully qualified, so it can still depend on the current working directory.

Consider adding a test for this case.

{
return tmp;
}

var temp = taskEnvironment.GetEnvironmentVariable("TEMP");
if (Path.IsPathRooted(temp))
{
return temp;
}

if (!string.IsNullOrEmpty(taskEnvironment.ProjectDirectory))
{
if (!string.IsNullOrEmpty(tmp))
{
return Path.Combine(taskEnvironment.ProjectDirectory, tmp);
}

if (!string.IsNullOrEmpty(temp))
{
return Path.Combine(taskEnvironment.ProjectDirectory, temp);
}
}

var userProfile = taskEnvironment.GetEnvironmentVariable("USERPROFILE");
if (Path.IsPathRooted(userProfile))
{
return userProfile;
}

return taskEnvironment.GetEnvironmentVariable("SYSTEMROOT");
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<OutputType>Library</OutputType>
<RootNamespace>Microsoft.CodeAnalysis.BuildTasks</RootNamespace>
<TargetFrameworks>$(NetRoslynSourceBuild);net472</TargetFrameworks>
<DefineConstants>$(DefineConstants);MICROSOFT_CODEANALYSIS_CONTRACTS_NO_VALUE_TASK</DefineConstants>
<DefineConstants>$(DefineConstants);MICROSOFT_CODEANALYSIS_CONTRACTS_NO_VALUE_TASK;MICROSOFT_CODEANALYSIS_MSBUILD_TASK</DefineConstants>
<!--
A .NET copy of this task assembly is included in the .NET SDK's Native AOT CLI, so it must be
clean for trimming, AOT, and single-file publishing. IsAotCompatible (enabled only for the .NET
Expand Down
36 changes: 23 additions & 13 deletions src/Compilers/Core/MSBuildTask/ManagedCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,11 @@ public string GeneratePathToTool()

protected override int ExecuteTool(string pathToTool, string responseFileCommands, string commandLineCommands)
{
using var innerLogger = new CompilerServerLogger($"MSBuild {Process.GetCurrentProcess().Id}");
using var innerLogger = new CompilerServerLogger(
$"MSBuild {Process.GetCurrentProcess().Id}",
loggingFilePath: null,
TaskEnvironment.GetEnvironmentVariable,
TaskEnvironment.GetFullPath);
var logger = new TaskCompilerServerLogger(Log, innerLogger);
return ExecuteTool(pathToTool, responseFileCommands, commandLineCommands, logger);
}
Expand All @@ -528,7 +532,7 @@ internal int ExecuteTool(string pathToTool, string responseFileCommands, string
var requestId = getRequestId();
logger.Log($"Compilation request {requestId}, PathToTool={pathToTool}");

string? tempDirectory = Path.GetTempPath();
string? tempDirectory = TaskEnvironment.GetTempPath();

if (!UseSharedCompilation ||
!UsingBuiltinTool ||
Expand All @@ -553,7 +557,10 @@ internal int ExecuteTool(string pathToTool, string responseFileCommands, string
// commandLineCommands (the parameter) may have been mucked with
// (to support using the dotnet cli)
var buildRequestArguments = GenerateCommandLineArgsList(responseFileCommands);
CompilerOptionParseUtilities.PrependFeatureFlagFromEnvironment(buildRequestArguments, logger.Log);
CompilerOptionParseUtilities.PrependFeatureFlagFromEnvironment(
buildRequestArguments,
TaskEnvironment.GetEnvironmentVariable,
logger.Log);
var buildRequest = BuildServerConnection.CreateBuildRequest(
requestId,
Language,
Expand All @@ -571,8 +578,9 @@ internal int ExecuteTool(string pathToTool, string responseFileCommands, string
buildRequest,
pipeName,
clientDirectory,
logger: logger,
cancellationToken: _sharedCompileCts.Token);
TaskEnvironment.GetEnvironmentVariables(),
logger,
_sharedCompileCts.Token);

responseTask.Wait(_sharedCompileCts.Token);

Expand Down Expand Up @@ -628,12 +636,12 @@ public override void Cancel()
/// </summary>
private string CurrentDirectoryToUse()
{
// ToolTask has a method for this. But it may return null. Use the process directory
// if ToolTask didn't override. MSBuild uses the process directory.
// ToolTask has a method for this. But it may return null. Use the task's project
// directory if ToolTask didn't override. This resolves against the task's execution environment.
string workingDirectory = GetWorkingDirectory();
if (string.IsNullOrEmpty(workingDirectory))
{
workingDirectory = Directory.GetCurrentDirectory();
workingDirectory = TaskEnvironment.ProjectDirectory;
}
return workingDirectory;
}
Expand All @@ -643,8 +651,8 @@ private string CurrentDirectoryToUse()
/// </summary>
private string? LibDirectoryToUse()
{
// First check the real environment.
string? libDirectory = Environment.GetEnvironmentVariable("LIB");
// First check the task environment.
string? libDirectory = TaskEnvironment.GetEnvironmentVariable("LIB");

// Now go through additional environment variables.
string[] additionalVariables = EnvironmentVariables;
Expand Down Expand Up @@ -1098,7 +1106,7 @@ private void NormalizePaths(ITaskItem[]? taskItems)

foreach (var item in taskItems)
{
item.ItemSpec = Utilities.GetFullPathNoThrow(item.ItemSpec);
item.ItemSpec = TaskEnvironment.GetFullPathNoThrow(item.ItemSpec);
}
}

Expand Down Expand Up @@ -1219,10 +1227,12 @@ protected bool CheckAllReferencesExistOnDisk()

foreach (ITaskItem reference in References)
{
if (!File.Exists(reference.ItemSpec))
var itemSpec = reference.ItemSpec;

if (string.IsNullOrEmpty(itemSpec) || !File.Exists(TaskEnvironment.GetFullPathNoThrow(itemSpec)))
{
success = false;
Comment thread
jaredpar marked this conversation as resolved.
Resolved
Log.LogErrorWithCodeFromResources("General_ReferenceDoesNotExist", reference.ItemSpec);
Log.LogErrorWithCodeFromResources("General_ReferenceDoesNotExist", itemSpec);
}
}

Expand Down
18 changes: 12 additions & 6 deletions src/Compilers/Core/MSBuildTask/ManagedToolTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,9 @@ protected sealed override string GenerateFullPathToTool()
// which means `ToolExe` is not really overridden by user (yes, the user sets it but basically to its default value).
ToolExe = null;

return UseAppHost ? PathToBuiltInTool : RuntimeHostInfo.GetDotNetPathOrDefault();
return UseAppHost
? PathToBuiltInTool
: RuntimeHostInfo.GetDotNetPathOrDefault(TaskEnvironment.GetEnvironmentVariable);
}
Comment thread
jaredpar marked this conversation as resolved.
Resolved

return Path.Combine(ToolPath ?? "", ToolExe);
Expand Down Expand Up @@ -319,20 +321,24 @@ protected override bool ValidateParameters()
{
// Set DOTNET_ROOT so that the apphost executables launch properly.
// Unset all other DOTNET_ROOT* variables so for example DOTNET_ROOT_X64 does not override ours.
if (IsBuiltinToolRunningOnCoreClr && RuntimeHostInfo.GetToolDotNetRoot(Log.LogMessage) is { } dotNetRoot)
if (IsBuiltinToolRunningOnCoreClr &&
RuntimeHostInfo.GetToolDotNetRoot(
TaskEnvironment.GetEnvironmentVariable,
Log.LogMessage) is { } dotNetRoot)
{
Log.LogMessage("Setting {0} to '{1}'", RuntimeHostInfo.DotNetRootEnvironmentName, dotNetRoot);
EnvironmentVariables =
[
.. EnvironmentVariables?.Where(static e => !e.StartsWith(RuntimeHostInfo.DotNetRootEnvironmentName, StringComparison.OrdinalIgnoreCase)) ?? [],
.. Environment.GetEnvironmentVariables().Cast<System.Collections.DictionaryEntry>()
.Where(e => ((string)e.Key).StartsWith(RuntimeHostInfo.DotNetRootEnvironmentName, StringComparison.OrdinalIgnoreCase))
.. EnvironmentVariables?.Where(static e => !e.StartsWith(RuntimeHostInfo.DotNetRootEnvironmentName, Environment.EnvironmentVariableComparison)) ?? [],
.. TaskEnvironment.GetEnvironmentVariables()
.Where(e => e.Key.StartsWith(RuntimeHostInfo.DotNetRootEnvironmentName, Environment.EnvironmentVariableComparison))
.Select(e => $"{e.Key}="),
$"{RuntimeHostInfo.DotNetRootEnvironmentName}={dotNetRoot}",
];
}

if (RuntimeHostInfo.ShouldDisableTieredCompilation && Environment.GetEnvironmentVariable(RuntimeHostInfo.DotNetTieredCompilationEnvironmentName) == null)
if (RuntimeHostInfo.ShouldDisableTieredCompilation &&
TaskEnvironment.GetEnvironmentVariable(RuntimeHostInfo.DotNetTieredCompilationEnvironmentName) == null)
{
var value = "0";
Log.LogMessage("Setting {0} to '{1}'", RuntimeHostInfo.DotNetTieredCompilationEnvironmentName, value);
Expand Down
21 changes: 19 additions & 2 deletions src/Compilers/Core/MSBuildTask/MapSourceRoots.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,24 @@ private static class Names
[return: NotNullIfNotNull(nameof(path))]
private static string? NormalizePath(string? path)
{
return string.IsNullOrEmpty(path) ? path : EnsureEndsWithSlash(Utilities.GetFullPathNoThrow(path));
// Delete this and call TaskEnvironment.GetFullPathNoThrow.
return string.IsNullOrEmpty(path) ? path : EnsureEndsWithSlash(GetFullPathNoThrow(path));

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@OvesN when I merge this PR it will create merge conflicts in yours. But your PR has access to TaskEnvironment in this type so you can make this method instance and then flip this to TaskEnvironment.GetFullPathNoThrow

}

/// <summary>
/// This will be removed in PR https://github.com/dotnet/roslyn/pull/84421 once these changes are
/// merged into the main branch. The TaskEnvironment.GetFullPathNoThrow method should be used instead.
/// </summary>
internal static string GetFullPathNoThrow(string path)
{
try
{
#pragma warning disable RS0030 // Do not used banned APIs
path = Path.GetFullPath(path);
#pragma warning restore RS0030 // Do not used banned APIs
}
catch (Exception e) when (Utilities.IsIoRelatedException(e)) { }
return path;
}

private static string EnsureEndsWithSlash(string path)
Expand Down Expand Up @@ -186,7 +203,7 @@ void setTopLevelMappedPaths(bool sourceControlled)
// Normalize nested root.
if (Utilities.TryCombine(containingRoot, nestedRoot, out var combinedPath))
{
var fullOriginalPath = Utilities.GetFullPathNoThrow(combinedPath);
var fullOriginalPath = GetFullPathNoThrow(combinedPath);
if (fullOriginalPath.StartsWith(containingRoot, StringComparison.OrdinalIgnoreCase))
{
nestedRoot = fullOriginalPath.Substring(containingRoot.Length);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<OutputType>Library</OutputType>
<RootNamespace>Microsoft.CodeAnalysis.BuildTasks</RootNamespace>
<TargetFramework>net472</TargetFramework>
<DefineConstants>$(DefineConstants);SDK_TASK;MICROSOFT_CODEANALYSIS_CONTRACTS_NO_VALUE_TASK</DefineConstants>
<DefineConstants>$(DefineConstants);SDK_TASK;MICROSOFT_CODEANALYSIS_CONTRACTS_NO_VALUE_TASK;MICROSOFT_CODEANALYSIS_MSBUILD_TASK</DefineConstants>

<!--
This task is the same as the MSBuild version but for net472 only. Our NRT setup does
Expand All @@ -20,9 +20,6 @@

<ItemGroup>
<InternalsVisibleTo Include="Microsoft.Build.Tasks.CodeAnalysis.Sdk.UnitTests" />
</ItemGroup>

<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)..\..\..\CSharp\csc\csc.rsp" CopyToOutputDirectory="PreserveNewest" />
<None Include="$(MSBuildThisFileDirectory)..\..\..\VisualBasic\vbc\vbc.rsp" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
Expand Down
Loading