Skip to content

Commit fe00457

Browse files
authored
[automated] Merge branch 'release/10.0.1xx' => 'main' (#50754)
2 parents 050ac05 + c83ceb0 commit fe00457

File tree

64 files changed

+674
-246
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+674
-246
lines changed

documentation/general/dotnet-run-file.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,8 @@ We always need to re-run MSBuild if implicit build files like `Directory.Build.p
295295
from `.cs` files, the only relevant MSBuild inputs are the `#:` directives,
296296
hence we can first check the `.cs` file timestamps and for those that have changed, compare the sets of `#:` directives.
297297
If only `.cs` files change, it is enough to invoke `csc.exe` (directly or via a build server)
298-
re-using command-line arguments that the last MSBuild invocation passed to the compiler.
298+
re-using command-line arguments that the last MSBuild invocation passed to the compiler
299+
(you can opt out of this via an MSBuild property `FileBasedProgramCanSkipMSBuild=false`).
299300
If no inputs change, it is enough to start the target executable without invoking the build at all.
300301

301302
## Alternatives and future work

eng/common/core-templates/job/source-build.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ parameters:
3434
# container and pool.
3535
platform: {}
3636

37+
# Optional list of directories to ignore for component governance scans.
38+
componentGovernanceIgnoreDirectories: []
39+
3740
is1ESPipeline: ''
3841

3942
# If set to true and running on a non-public project,
@@ -94,3 +97,4 @@ jobs:
9497
parameters:
9598
is1ESPipeline: ${{ parameters.is1ESPipeline }}
9699
platform: ${{ parameters.platform }}
100+
componentGovernanceIgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }}

eng/common/core-templates/jobs/source-build.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ parameters:
1515
# one job runs on 'defaultManagedPlatform'.
1616
platforms: []
1717

18+
# Optional list of directories to ignore for component governance scans.
19+
componentGovernanceIgnoreDirectories: []
20+
1821
is1ESPipeline: ''
1922

2023
# If set to true and running on a non-public project,
@@ -31,6 +34,7 @@ jobs:
3134
is1ESPipeline: ${{ parameters.is1ESPipeline }}
3235
jobNamePrefix: ${{ parameters.jobNamePrefix }}
3336
platform: ${{ platform }}
37+
componentGovernanceIgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }}
3438
enableInternalSources: ${{ parameters.enableInternalSources }}
3539

3640
- ${{ if eq(length(parameters.platforms), 0) }}:
@@ -39,4 +43,5 @@ jobs:
3943
is1ESPipeline: ${{ parameters.is1ESPipeline }}
4044
jobNamePrefix: ${{ parameters.jobNamePrefix }}
4145
platform: ${{ parameters.defaultManagedPlatform }}
46+
componentGovernanceIgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }}
4247
enableInternalSources: ${{ parameters.enableInternalSources }}

eng/common/core-templates/steps/source-build.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ parameters:
1111
# for details. The entire object is described in the 'job' template for simplicity, even though
1212
# the usage of the properties on this object is split between the 'job' and 'steps' templates.
1313
platform: {}
14+
15+
# Optional list of directories to ignore for component governance scans.
16+
componentGovernanceIgnoreDirectories: []
17+
1418
is1ESPipeline: false
1519

1620
steps:

src/Cli/Microsoft.DotNet.Cli.Utils/Constants.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@ public static class Constants
2626
public static readonly string EnableDefaultEmbeddedResourceItems = nameof(EnableDefaultEmbeddedResourceItems);
2727
public static readonly string EnableDefaultNoneItems = nameof(EnableDefaultNoneItems);
2828

29+
// MSBuild targets
30+
public const string Build = nameof(Build);
31+
public const string ComputeRunArguments = nameof(ComputeRunArguments);
32+
public const string CoreCompile = nameof(CoreCompile);
33+
34+
// MSBuild item metadata
35+
public const string Identity = nameof(Identity);
36+
public const string FullPath = nameof(FullPath);
37+
2938
public static readonly string ProjectArgumentName = "<PROJECT>";
3039
public static readonly string SolutionArgumentName = "<SLN_FILE>";
3140
public static readonly string ToolPackageArgumentName = "<PACKAGE_ID>";

src/Cli/dotnet/Commands/Run/CSharpCompilerCommand.cs

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,20 @@ internal sealed partial class CSharpCompilerCommand
5050
public required string ArtifactsPath { get; init; }
5151
public required bool CanReuseAuxiliaryFiles { get; init; }
5252

53+
public string BaseDirectory => field ??= Path.GetDirectoryName(EntryPointFileFullPath)!;
54+
55+
/// <summary>
56+
/// Compiler command line arguments to use. If empty, default arguments are used.
57+
/// These should be already properly escaped.
58+
/// </summary>
59+
public required ImmutableArray<string> CscArguments { get; init; }
60+
61+
/// <summary>
62+
/// Path to the <c>bin/Program.dll</c> file. If specified,
63+
/// the compiled output (<c>obj/Program.dll</c>) will be copied to this location.
64+
/// </summary>
65+
public required string? BuildResultFile { get; init; }
66+
5367
/// <param name="fallbackToNormalBuild">
5468
/// Whether the returned error code should not cause the build to fail but instead fallback to full MSBuild.
5569
/// </param>
@@ -64,7 +78,7 @@ public int Execute(out bool fallbackToNormalBuild)
6478
requestId: EntryPointFileFullPath,
6579
language: RequestLanguage.CSharpCompile,
6680
arguments: ["/noconfig", "/nologo", $"@{EscapeSingleArg(rspPath)}"],
67-
workingDirectory: Environment.CurrentDirectory,
81+
workingDirectory: BaseDirectory,
6882
tempDirectory: Path.GetTempPath(),
6983
keepAlive: null,
7084
libDirectory: null,
@@ -87,7 +101,18 @@ public int Execute(out bool fallbackToNormalBuild)
87101
cancellationToken: default);
88102

89103
// Process the response.
90-
return ProcessBuildResponse(responseTask.Result, out fallbackToNormalBuild);
104+
var exitCode = ProcessBuildResponse(responseTask.Result, out fallbackToNormalBuild);
105+
106+
// Copy from obj to bin.
107+
if (BuildResultFile != null &&
108+
CSharpCommandLineParser.Default.Parse(CscArguments, BaseDirectory, sdkDirectory: null) is { OutputFileName: { } outputFileName } parsedArgs)
109+
{
110+
var objFile = parsedArgs.GetOutputFilePath(outputFileName);
111+
Reporter.Verbose.WriteLine($"Copying '{objFile}' to '{BuildResultFile}'.");
112+
File.Copy(objFile, BuildResultFile, overwrite: true);
113+
}
114+
115+
return exitCode;
91116

92117
static string GetCompilerCommitHash()
93118
{
@@ -129,6 +154,14 @@ static int ProcessBuildResponse(BuildResponse response, out bool fallbackToNorma
129154

130155
private void PrepareAuxiliaryFiles(out string rspPath)
131156
{
157+
rspPath = Path.Join(ArtifactsPath, "csc.rsp");
158+
159+
if (!CscArguments.IsDefaultOrEmpty)
160+
{
161+
File.WriteAllLines(rspPath, CscArguments);
162+
return;
163+
}
164+
132165
string fileDirectory = Path.GetDirectoryName(EntryPointFileFullPath) ?? string.Empty;
133166
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(EntryPointFileFullPath);
134167

@@ -283,7 +316,6 @@ private void PrepareAuxiliaryFiles(out string rspPath)
283316
""");
284317
}
285318

286-
rspPath = Path.Join(ArtifactsPath, "csc.rsp");
287319
if (ShouldEmit(rspPath))
288320
{
289321
IEnumerable<string> args = GetCscArguments(
@@ -315,18 +347,18 @@ private static string EscapeSingleArg(string arg)
315347
{
316348
if (IsPathOption(arg, out var colonIndex))
317349
{
318-
return arg[..(colonIndex + 1)] + EscapeCore(arg[(colonIndex + 1)..]);
350+
return arg[..(colonIndex + 1)] + EscapePathArgument(arg[(colonIndex + 1)..]);
319351
}
320352

321-
return EscapeCore(arg);
353+
return EscapePathArgument(arg);
354+
}
322355

323-
static string EscapeCore(string arg)
356+
internal static string EscapePathArgument(string arg)
357+
{
358+
return ArgumentEscaper.EscapeSingleArg(arg, additionalShouldSurroundWithQuotes: static (string arg) =>
324359
{
325-
return ArgumentEscaper.EscapeSingleArg(arg, additionalShouldSurroundWithQuotes: static (string arg) =>
326-
{
327-
return arg.ContainsAny(s_additionalShouldSurroundWithQuotes);
328-
});
329-
}
360+
return arg.ContainsAny(s_additionalShouldSurroundWithQuotes);
361+
});
330362
}
331363

332364
public static bool IsPathOption(string arg, out int colonIndex)

src/Cli/dotnet/Commands/Run/RunCommand.cs

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -338,8 +338,8 @@ private VirtualProjectBuildingCommand CreateVirtualCommand()
338338
Debug.Assert(EntryPointFileFullPath != null);
339339

340340
var args = MSBuildArgs.RequestedTargets is null or []
341-
? MSBuildArgs.CloneWithAdditionalTargets("Build", ComputeRunArgumentsTarget)
342-
: MSBuildArgs.CloneWithAdditionalTargets(ComputeRunArgumentsTarget);
341+
? MSBuildArgs.CloneWithAdditionalTargets(Constants.Build, Constants.ComputeRunArguments, Constants.CoreCompile)
342+
: MSBuildArgs.CloneWithAdditionalTargets(Constants.ComputeRunArguments, Constants.CoreCompile);
343343

344344
return new(
345345
entryPointFileFullPath: EntryPointFileFullPath,
@@ -378,6 +378,14 @@ private MSBuildArgs SetupSilentBuildArgs(MSBuildArgs msbuildArgs)
378378

379379
internal ICommand GetTargetCommand(Func<ProjectCollection, ProjectInstance>? projectFactory, RunProperties? cachedRunProperties)
380380
{
381+
if (cachedRunProperties != null)
382+
{
383+
// We can skip project evaluation if we already evaluated the project during virtual build
384+
// or we have cached run properties in previous run (and this is a --no-build or skip-msbuild run).
385+
Reporter.Verbose.WriteLine("Getting target command: from cache.");
386+
return CreateCommandFromRunProperties(cachedRunProperties.WithApplicationArguments(ApplicationArgs));
387+
}
388+
381389
if (projectFactory is null && ProjectFileFullPath is null)
382390
{
383391
// If we are running a file-based app and projectFactory is null, it means csc was used instead of full msbuild.
@@ -387,14 +395,6 @@ internal ICommand GetTargetCommand(Func<ProjectCollection, ProjectInstance>? pro
387395
return CreateCommandForCscBuiltProgram(EntryPointFileFullPath);
388396
}
389397

390-
if (cachedRunProperties != null)
391-
{
392-
// We can also skip project evaluation if we already evaluated the project during virtual build
393-
// or we have cached run properties in previous run (and this is a --no-build run).
394-
Reporter.Verbose.WriteLine("Getting target command: from cache.");
395-
return CreateCommandFromRunProperties(cachedRunProperties.WithApplicationArguments(ApplicationArgs));
396-
}
397-
398398
Reporter.Verbose.WriteLine("Getting target command: evaluating project.");
399399
FacadeLogger? logger = LoggerUtility.DetermineBinlogger([.. MSBuildArgs.OtherMSBuildArgs], "dotnet-run");
400400
var project = EvaluateProject(ProjectFileFullPath, projectFactory, MSBuildArgs, logger);
@@ -487,15 +487,13 @@ static void InvokeRunArgumentsTarget(ProjectInstance project, bool noBuild, Faca
487487
loggersForBuild.Add(binaryLogger);
488488
}
489489

490-
if (!project.Build([ComputeRunArgumentsTarget], loggers: loggersForBuild, remoteLoggers: null, out _))
490+
if (!project.Build([Constants.ComputeRunArguments], loggers: loggersForBuild, remoteLoggers: null, out _))
491491
{
492-
throw new GracefulException(CliCommandStrings.RunCommandEvaluationExceptionBuildFailed, ComputeRunArgumentsTarget);
492+
throw new GracefulException(CliCommandStrings.RunCommandEvaluationExceptionBuildFailed, Constants.ComputeRunArguments);
493493
}
494494
}
495495
}
496496

497-
static readonly string ComputeRunArgumentsTarget = "ComputeRunArguments";
498-
499497
internal static void ThrowUnableToRunError(ProjectInstance project)
500498
{
501499
string targetFrameworks = project.GetPropertyValue("TargetFrameworks");

0 commit comments

Comments
 (0)