Skip to content

Local dev props #48739

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ obj/
.tools/
.packages/

# Locally-customizable build props import
/LocalDev.Build.props
/LocalDev.Packages.props

# OS X Device Services Store
.DS_Store

Expand Down
5 changes: 5 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,9 @@

<Import Project="build/GenerateResxSource.targets" />

<!-- Import any local dev properties if they exist. -->
<PropertyGroup>
<LocalDevPropsPath>$(MSBuildThisFileDirectory)LocalDev.Build.props</LocalDevPropsPath>
</PropertyGroup>
<Import Project="$(LocalDevPropsPath)" Condition="Exists('$(LocalDevPropsPath)') AND '$(SkipLocalDevSettings)' != 'true'" />
</Project>
6 changes: 6 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -157,4 +157,10 @@
<PackageVersion Include="Microsoft.Build.Utilities.Core" Version="$(MicrosoftBuildMinimumVersion)" />
<PackageVersion Include="Microsoft.NET.StringTools" Version="$(MicrosoftBuildMinimumVersion)" />
</ItemGroup>

<!-- Import any local dev packages if they exist. -->
<PropertyGroup>
<LocalDevPackagesPath>$(MSBuildThisFileDirectory)LocalDev.Packages.props</LocalDevPackagesPath>
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems weird to me to have LocalDev.Packages.props and LocalDev.Build.props start in 'documentation' (which shouldn't have code, in my opinion) and need someone to copy them to the root. Perhaps we could have both always in the root (or, better yet, root/LocalDevTools or just root/eng) and import them conditionally if -p:SomeProperty=true?

Copy link
Member Author

Choose a reason for hiding this comment

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

They need to be available when building from VS.
Also, these are just templates. They need to be updated to point to the local Roslyn repo and set the local version. That information is specific to the dev machine.

</PropertyGroup>
<Import Project="$(LocalDevPackagesPath)" Condition="Exists('$(LocalDevPackagesPath)') AND '$(SkipLocalDevSettings)' != 'true'" />
</Project>
19 changes: 19 additions & 0 deletions documentation/local-dev/roslyn/LocalDev.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project>
<!-- If \LocalDev.Build.props exists, it will be loaded and merged with Directory.Build.props, allowing for local adhoc build customizations. -->
<PropertyGroup>
<RoslynRoot>$(MSBuildThisFileDirectory)..\roslyn</RoslynRoot>
<RestoreAdditionalProjectSources>$(RestoreAdditionalProjectSources);$(RoslynRoot)\artifacts\packages\Debug\Shipping</RestoreAdditionalProjectSources>

<!--
Keep downloaded packages in .\packages to avoid corrupting the shared global packages cache, but do allow the
use of the shared cache as a fallback folder so packages already downloaded do not need to be downloaded again.
-->
<RestorePackagesPath>$(MSBuildThisFileDirectory).packages\</RestorePackagesPath>
<RestoreFallbackFolders>$(UserProfile)\.nuget\packages</RestoreFallbackFolders>
</PropertyGroup>

<!-- RECOMMENDED: Add a target which prints a message saying that this file has been imported. -->
<Target Name="DisplayMessageIfLocalDevPropsDefined" BeforeTargets="BeforeCompile">
<Message Text="$(MSBuildProjectName) $(TargetFramework): Imported local dev properties from $(MSBuildThisFileFullPath)." Importance="high" />
</Target>
</Project>
24 changes: 24 additions & 0 deletions documentation/local-dev/roslyn/LocalDev.Packages.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project>
<!-- If \LocalDev.Packages.props exists, it will be loaded and merged with Directory.Packages.props, allowing for local adhoc build customizations. -->
<PropertyGroup>
<!-- Use the local version of Roslyn -->
<RoslynVersion>4.14.0-dev</RoslynVersion>
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there any way to update these versions?

Copy link
Member Author

@tmat tmat Apr 28, 2025

Choose a reason for hiding this comment

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

How? These are locally built versions.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure. I was thinking that if it's built locally, we could perhaps overwrite something in this file as part of the build process? That only really works if it's in a fixed location and we just conditionally import it rather than having it normally live in documentation as here.

Copy link
Member Author

Choose a reason for hiding this comment

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

We could potentially fish out the version from the other repo, using RoslynRoot set in LocalDev.Build.props. Setting RoslynVersion in LocalDev.Packages.props is easy enough, one time step though.

<RoslynAnalyzers>3.12.0-dev</RoslynAnalyzers>

<MicrosoftNetCompilersToolsetVersion>$(RoslynVersion)</MicrosoftNetCompilersToolsetVersion>
<MicrosoftNetCompilersToolsetFrameworkPackageVersion>$(RoslynVersion)</MicrosoftNetCompilersToolsetFrameworkPackageVersion>
<MicrosoftCodeAnalysisPackageVersion>$(RoslynVersion)</MicrosoftCodeAnalysisPackageVersion>
<MicrosoftCodeAnalysisCSharpPackageVersion>$(RoslynVersion)</MicrosoftCodeAnalysisCSharpPackageVersion>
<MicrosoftCodeAnalysisCSharpCodeStylePackageVersion>$(RoslynVersion)</MicrosoftCodeAnalysisCSharpCodeStylePackageVersion>
<MicrosoftCodeAnalysisCSharpFeaturesPackageVersion>$(RoslynVersion)</MicrosoftCodeAnalysisCSharpFeaturesPackageVersion>
<MicrosoftCodeAnalysisWorkspacesCommonPackageVersion>$(RoslynVersion)</MicrosoftCodeAnalysisWorkspacesCommonPackageVersion>
<MicrosoftCodeAnalysisWorkspacesMSBuildPackageVersion>$(RoslynVersion)</MicrosoftCodeAnalysisWorkspacesMSBuildPackageVersion>
<MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>$(RoslynVersion)</MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>
<MicrosoftCodeAnalysisPublicApiAnalyzersVersion>$(RoslynAnalyzers)</MicrosoftCodeAnalysisPublicApiAnalyzersVersion>
</PropertyGroup>

<!-- RECOMMENDED: Add a target which prints a message saying that this file has been imported. -->
<Target Name="DisplayMessageIfLocalDevPackagesDefined" BeforeTargets="BeforeCompile">
<Message Text="$(MSBuildProjectName) $(TargetFramework): Imported local dev packages from $(MSBuildThisFileFullPath)." Importance="high" />
</Target>
</Project>
37 changes: 37 additions & 0 deletions documentation/local-dev/roslyn/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Instructions for Roslyn developers

1. Check out a working copy of dotnet/roslyn, e.g. to the directory next to this repo's root `..\roslyn`.
Make sure the current working directory is the checkout of this repo.

2. Copy LocalDev.Build.props to the root and set `RoslynRoot` property in the copied file to local Roslyn repo.

`cp documentation\local-dev\roslyn\LocalDev.Build.props LocalDev.Build.props`

3. Copy LocalDev.Packages.props.roslyn to the root

`cp documentation\local-dev\roslyn\LocalDev.Packages.props LocalDev.Packages.props`

4. Build Roslyn with:

`..\roslyn\Build.cmd -restore -pack`
Copy link
Member

Choose a reason for hiding this comment

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

Consider a simpler approach (which is what I do currently and it works great):

  1. Build Roslyn: .\build.cmd -pack /p:VersionSuffix=$(git rev-parse --short HEAD)
  2. In SDK's Versions.props: find+replace (simple VSCode action) current roslyn version with the built version
  3. Restore/build SDK.

That's it. No need to clean .packages. No need to keep the list of Version properties in LocalDev.Packages.props in sync with Versions.props (if we add more roslyn dependencies over time). Works in other repos too (like runtime or razor).

Copy link
Member Author

@tmat tmat Apr 30, 2025

Choose a reason for hiding this comment

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

It's not simpler. I don't need to build and pack the entire Roslyn from command line, which takes a long time. I can pack just one project from VS. I don't need to update version every time I make a change. I only need to delete Roslyn packages from .packages dir and restore. Ideally, I would not want to do that either. I wonder if we can set the VersionSuffix automatically to what you do when building locally. Then in LocalDev.Packages.props we would use x.y.z-dev-* pattern.

No need to keep the list of Version properties in LocalDev.Packages.props

If you update the version in Versions.props you need to revert that change before committing.

Copy link
Member

Choose a reason for hiding this comment

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

I don't need to build and pack the entire Roslyn from command line, which takes a long time. I can pack just one project from VS.

I see, the doc says build.cmd -pack so I assumed that's what you are doing.

I don't need to update version every time I make a change. I only need to delete Roslyn packages from .packages dir and restore.

Both are a single step, I don't think one is more difficult than the other.

But it's true that re-building just a single package with my approach isn't feasible. Your approach looks better in this scenario. Thanks for explaining.

Copy link
Member Author

Choose a reason for hiding this comment

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

Another issue with using $(git rev-parse --short HEAD) is that you need to remember to commit each time you want to switch to the other repo.

Copy link
Member Author

Choose a reason for hiding this comment

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

I think setting VersionSuffix to current time-based value would make it simpler still. Might explore that later on.


5. Clear the customized packages cache in `.packages`

`git clean -dxf .packages/`
Copy link
Member

Choose a reason for hiding this comment

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

Why are you using git clean and not simply rm -r?

Copy link
Member Author

Choose a reason for hiding this comment

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

Either way works. I just delete the directory from file explorer. @sharwell authored the original doc.


6. Restore packages

7. Open solution and work normally

8. Following another change to Roslyn.sln, repeat steps 4-6 to pick up those changes in sdk.

Tip to speed up restore if .\packages starts containing more than just the Roslyn development packages. Clear the
packages cache, and restore packages without using the customized local developer settings to update the per-user
NuGet global package cache with the default packages used for Conversations. Then run a second restore to pick up
just the local development packages for Roslyn.

```
git clean -dxf .packages/
restore /p:SkipLocalDevSettings=true
restore
```
Loading