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
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,8 @@ private static MSBuildProjectInfo GetInnerBuildOrDefault(MSBuildProjectInfo proj
/// Determines if a project is self-contained using MSBuild properties from the binlog.
/// Reads the SelfContained and PublishAot properties directly.
/// </summary>
private static bool IsSelfContainedFromProjectInfo(MSBuildProjectInfo projectInfo) =>
projectInfo.SelfContained == true || projectInfo.PublishAot == true;
private static bool? IsSelfContainedFromProjectInfo(MSBuildProjectInfo projectInfo) =>
projectInfo.SelfContained ?? (projectInfo.PublishAot == true ? true : null);

private void ProcessBinlogFile(string binlogPath, CancellationToken cancellationToken)
{
Expand Down Expand Up @@ -389,7 +389,8 @@ private void RegisterDotNetComponent(MSBuildProjectInfo projectInfo, string reco

var singleFileComponentRecorder = this.ComponentRecorder.CreateSingleFileComponentRecorder(recorderLocation);

// Primary self-contained check from binlog properties (SelfContained, PublishAot)
// Prefer an explicit SelfContained value from the binlog; use PublishAot as a positive signal.
// A null result means the lock file heuristic may be used as a fallback.
var isSelfContainedFromBinlog = IsSelfContainedFromProjectInfo(projectInfo);

if (lockFile != null)
Expand All @@ -401,7 +402,7 @@ private void RegisterDotNetComponent(MSBuildProjectInfo projectInfo, string reco
{
var innerInfo = GetInnerBuildOrDefault(projectInfo, target.TargetFramework);
var targetType = GetTargetType(innerInfo.OutputType);
var isSelfContained = isSelfContainedFromBinlog ||
var isSelfContained = isSelfContainedFromBinlog ??
LockFileUtilities.IsSelfContainedFromLockFile(lockFile.PackageSpec, target.TargetFramework, target);
var projectType = LockFileUtilities.GetTargetTypeWithSelfContained(targetType, isSelfContained);
var frameworkName = target.TargetFramework?.GetShortFolderName();
Expand All @@ -420,7 +421,7 @@ private void RegisterDotNetComponent(MSBuildProjectInfo projectInfo, string reco
// Binlog-only path: no lock file available or no targets in lock file
// Determine target type from outer build OutputType property.
var targetTypeFromBinlog = GetTargetType(projectInfo.OutputType);
var projectTypeFromBinlog = LockFileUtilities.GetTargetTypeWithSelfContained(targetTypeFromBinlog, isSelfContainedFromBinlog);
var projectTypeFromBinlog = LockFileUtilities.GetTargetTypeWithSelfContained(targetTypeFromBinlog, isSelfContainedFromBinlog ?? false);

// Get target frameworks from binlog properties
var targetFrameworks = new List<string>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,25 @@ public async Task WithBinlog_NotSelfContained_RegistersPlainApplication()
dotNet.ProjectType.Should().Be("application");
}

[TestMethod]
public async Task WithBinlog_ExplicitSelfContainedFalse_OverridesLockFileRuntimePackHeuristic()
{
var info = CreateProjectInfo();
info.NETCoreSdkVersion = "8.0.100";
info.OutputType = "Library";
info.SelfContained = false;
var assetsJson = RuntimePackDownloadAssetsJson();

var (result, recorder) = await ExecuteWithBinlogAsync([info], assetsJson);

result.ResultCode.Should().Be(ProcessingResultCode.Success);
var dotNet = recorder.GetDetectedComponents()
.Where(c => c.Component is DotNetComponent)
.Select(c => (DotNetComponent)c.Component)
.Single();
dotNet.ProjectType.Should().Be("library");
}

[TestMethod]
public async Task WithBinlog_MultiTarget_PerTfmDevDependency()
{
Expand Down Expand Up @@ -934,6 +953,18 @@ private static string SimpleAssetsJson(string packageName, string version) => $$
}
""";

private static string RuntimePackDownloadAssetsJson()
{
const string frameworkDependencies = "\"dependencies\": {";
const string runtimePackDownload = """
"frameworkReferences": { "Microsoft.NETCore.App": { "privateAssets": "all" } },
"downloadDependencies": [ { "name": "Microsoft.NETCore.App.Runtime.linux-x64", "version": "[8.0.0, 8.0.0]" } ],
"dependencies": {
""";
return SimpleAssetsJson("Newtonsoft.Json", "13.0.1")
.Replace(frameworkDependencies, runtimePackDownload, StringComparison.Ordinal);
}

/// <summary>
/// Assets JSON with a top-level package that has a transitive dependency.
/// Microsoft.Extensions.Logging → Microsoft.Extensions.Logging.Abstractions.
Expand Down