Skip to content

start-vs-VisualFSharpSln.ps1: build against a locally built hive Roslyn from its own packages - #20528

Open
xperiandri wants to merge 3 commits into
dotnet:mainfrom
xperiandri:start-vs-local-roslyn-packages
Open

xperiandri wants to merge 3 commits into
dotnet:mainfrom
xperiandri:start-vs-local-roslyn-packages

Conversation

@xperiandri

Copy link
Copy Markdown
Contributor

Description

Depends on #20467, which is the base of this branch. Only the last commit, "Build against a locally built hive Roslyn from its own packages", belongs to this pull request; please review it after #20467 merges.

#20467 teaches the script to read the Roslyn deployed in the target hive. When that Roslyn is a local build (a -dev version), it either matched the minor the repo flows and wrote no override, or stopped and asked for -RoslynVersion. Neither builds against the Roslyn F5 actually runs.

A Roslyn is built locally and deployed into a hive because its API surface differs from the flowed package: it is where an ExternalAccess contract lives before it flows. So a matching minor says nothing about whether the flowed packages will do, and asking for a published version gives up on the one that differs.

With this change:

  • A -dev version always overrides the flowed packages.
  • The override adds that Roslyn build's package folders to RestoreAdditionalProjectSources, because no feed carries its version. This has to go through the props import: Microsoft.FSharp.NetSdk.targets declares the property TreatAsLocalProperty and appends to it, so a command-line value would not survive.
  • -RoslynRepo names the Roslyn repository, defaulting to a roslyn folder next to this one. The script checks that it holds the package for that version and says so, instead of restore failing halfway with NU1101.

Shipped Roslyn versions behave as in #20467.

Checked with -DryRun:

Hive Roslyn found Result
RoslynDev 5.12.5-dev, deployed there override with the Roslyn repo's Shipping and NonShipping package folders
Foo none, so the installed 5.11.0-1.26424.5 override without extra sources
RoslynDev with -RoslynRepo C:\no-such-roslyn 5.12.5-dev stops with "no repository at C:\no-such-roslyn; pass -RoslynRepo"

Tooling only; no compiler or IDE code path changes, so no release notes entry.

Checklist

  • Test cases added
  • Performance benchmarks added in case of performance changes
  • Release notes entry updated

🤖 Generated with Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

✅ No release notes required

@github-actions github-actions Bot added ⚠️ Affects-Build-Infra Tooling check: PR touches build infrastructure ⚠️ Affects-Restore Tooling check: PR touches NuGet packages or feeds labels Sep 11, 2026
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@T-Gro T-Gro left a comment

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.

🤖 🕵️ AI review — verify independently.

Comment thread start-vs-VisualFSharpSln.ps1 Outdated
# RestoreAdditionalProjectSources has to arrive through the props import rather than on the command
# line: Microsoft.FSharp.NetSdk.targets declares it TreatAsLocalProperty and appends to it.
$sources =
if ($feeds) { "<RestoreAdditionalProjectSources>`$(RestoreAdditionalProjectSources);$($feeds -join ';')</RestoreAdditionalProjectSources>" }

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.

🤖 🕵️ [P2] Repacked Roslyn packages ignored when the -dev version is unchanged: restore succeeds with the previous contents from NuGet's global-packages cache, despite the updated local feed.

.\start-vs-VisualFSharpSln.ps1 -RoslynVersion 5.10.0-dev -RoslynRepo 'C:\src\roslyn'
# Change Roslyn APIs, rebuild and repack as the same 5.10.0-dev version.
.\start-vs-VisualFSharpSln.ps1 -RoslynVersion 5.10.0-dev -RoslynRepo 'C:\src\roslyn'
# Still consumes the first build's packages until their cache entries are removed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 1e2c85b: before restore, the script removes the global-packages entry ($env:NUGET_PACKAGES or ~\.nuget\packages) of every package the local feeds hold at that -dev version; -DryRun lists them instead.

Comment thread start-vs-VisualFSharpSln.ps1 Outdated
throw "$RootSuffix runs a locally built Roslyn $version, which only its own packages provide, but there is no repository at $repo; pass -RoslynRepo."
}

$feeds = 'Shipping', 'NonShipping' | ForEach-Object { Join-Path $repo "artifacts\packages\Release\$_" }

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.

🤖 🕵️ [P2] Valid relative repository passes validation but nested projects fail restore with NU1301: NuGet resolves the emitted relative sources against each project directory, not the launcher's working directory.

# From the F# checkout, with packed Roslyn packages in the sibling checkout:
.\start-vs-VisualFSharpSln.ps1 -RoslynVersion 5.12.0-dev -RoslynRepo '..\roslyn'

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 1e2c85b: -RoslynRepo is resolved to an absolute path against the current location before the feeds are built.

Comment thread start-vs-VisualFSharpSln.ps1 Outdated
# RestoreAdditionalProjectSources has to arrive through the props import rather than on the command
# line: Microsoft.FSharp.NetSdk.targets declares it TreatAsLocalProperty and appends to it.
$sources =
if ($feeds) { "<RestoreAdditionalProjectSources>`$(RestoreAdditionalProjectSources);$($feeds -join ';')</RestoreAdditionalProjectSources>" }

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.

🤖 🕵️ [P2] & in an existing repository path makes the generated override invalid XML; restore stops with MSB4024 while parsing the unescaped feed path.

.\start-vs-VisualFSharpSln.ps1 -RoslynVersion 5.12.0-dev -RoslynRepo 'C:\src\roslyn&tree'

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 1e2c85b: the feed paths are XML-escaped (SecurityElement.Escape) when written into the props.

Comment thread start-vs-VisualFSharpSln.ps1 Outdated
# less about that than a message here does.
function Get-RoslynDevFeeds([string]$repo, [string]$version) {
if (-not $repo) { $repo = Join-Path (Split-Path $PSScriptRoot) 'roslyn' }
if (-not (Test-Path $repo)) {

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.

🤖 🕵️ [P2] Existing roslyn[1] repository rejected as nonexistent: both new Test-Path checks interpret brackets as wildcards instead of literal path characters.

.\start-vs-VisualFSharpSln.ps1 -RoslynVersion 5.12.0-dev -RoslynRepo 'C:\src\roslyn[1]'

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 1e2c85b: every Test-Path and Get-ChildItem in the script now uses -LiteralPath.

@T-Gro T-Gro added the AI-reviewed PR reviewed by AI review council label Sep 14, 2026
@T-Gro
T-Gro self-requested a review September 14, 2026 14:28
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions github-actions Bot added the ⚠️ Affects-Design-Time Tooling check: PR touches type providers or dependency manager label Sep 24, 2026
@github-actions

This comment has been minimized.

@github-actions

Copy link
Copy Markdown
Contributor

🔍 Tooling Safety Check — Affects-Build-Infra, Affects-Design-Time, Affects-Restore
Affects-Build-Infra: Changes generated MSBuild configuration.
Affects-Design-Time: Changes Visual Studio launch behavior.
Affects-Restore: Changes package restore sources.

Generated by PR Tooling Safety Check · gpt56 1.7M · ◷

Copilot AI balanced review requested due to automatic review settings September 29, 2026 16:56

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

A missing package folder can break restore, and clearing the shared NuGet cache can disrupt other builds.

Review effort: Balanced
Findings: 1 High severity · 1 Medium severity

Open (2)
What changed in this PR

This PR lets the Visual Studio launch script build the F# extension against a locally built Roslyn deployed in the target hive, using that Roslyn build’s own packages.

Changes:

  • Override flowed Roslyn packages whenever the hive uses a -dev build.
  • Add the local Roslyn package folders as restore sources and clear cached copies before restoring.
File Description
start-vs-VisualFSharpSln.ps1 Locates local Roslyn packages and configures the override, restore, and launch.

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Write-Host "Would restore, then open $Solution in $DevEnv; F5 deploys into and launches $RootSuffix"
return
}
$stale | ForEach-Object { Remove-Item -LiteralPath $_ -Recurse -Force }

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Keeping the shared cache. Only <id>/<version> entries at the -dev version are removed, and only for packages the local Roslyn feeds hold at that version. No published package carries that version, so nothing restored from a real feed is affected. The only other readers are builds against this same local Roslyn pack, and those would pick up the stale copy anyway.

A separate cache per launch would re-download every package the repo restores on each launch, and the launched VS would keep that cache for all its builds. Arcade deliberately keeps dev builds on the global cache to avoid that cost (InitializeNuGetPackageCachePath in eng/common/tools.ps1).

Comment thread start-vs-VisualFSharpSln.ps1 Outdated
@xperiandri
xperiandri force-pushed the start-vs-local-roslyn-packages branch from 84f3cdc to c820c98 Compare October 2, 2026 16:03

@T-Gro T-Gro left a comment

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.

🤖 🕵️ Re-reviewed all recent changes as of c820c98; LGTM

xperiandri and others added 3 commits October 8, 2026 02:58
A Roslyn built locally and deployed into the hive is there because
its API surface differs from the flowed package: it is where an
ExternalAccess contract lives before it flows. Matching the minor the
repo flows therefore says nothing about whether the flowed packages
will do, and refusing the dev version left no way to build against
the Roslyn F5 actually runs.

A dev version now always overrides, and the override adds the package
folders of that Roslyn build to RestoreAdditionalProjectSources, since
no feed carries its version. -RoslynRepo names the repository, next to
this one by default, and the script checks that it actually holds the
package before restore fails halfway with NU1101.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…d drop stale -dev packages

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@xperiandri
xperiandri force-pushed the start-vs-local-roslyn-packages branch from c820c98 to 4a165d7 Compare October 8, 2026 01:11

@T-Gro T-Gro left a comment

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.

🤖 🕵️ Re-reviewed all recent changes as of 4a165d7; LGTM

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

⚠️ Affects-Build-Infra Tooling check: PR touches build infrastructure ⚠️ Affects-Design-Time Tooling check: PR touches type providers or dependency manager ⚠️ Affects-Restore Tooling check: PR touches NuGet packages or feeds AI-reviewed PR reviewed by AI review council

Projects

Status: New

Development

Successfully merging this pull request may close these issues.

3 participants