Closed srivatsn closed 1 year ago
Moving to the msbuild repo where the design for this needs to happen.
This isn't in our power alone, unfortunately. MSBuild is one consumer of the solution format, but arguably not the most important one: Visual Studio itself reads solutions when loading and that code is the canonical copy.
This has been put off for almost 15 years now, so I'm pessimistic--but it's a totally reasonable request, and maybe now is the time it can actually get done.
Personally, I'd like to see a native MSBuild format rather than a distinct XML schema. But representing all the data in MSBuild could be pretty tricky.
+1 for replacing the .sln file with native msbuild files. This probably implies implementing lineup files in one form or another (see lineup files in #1493). And then, probably, also the notion "project cones".
Clearly I'm misunderstanding what the role of the sln file actually is, I thought it was merely for VisualStudio but at build time it would pass the relevant csproj files down to msbuild, and that msbuild only deals with those.
But yes, I understand this is not a quick thing to do and requires major efforts across various teams (and companies), but given the effort to simplify csproj files was so well received, we should still strive for it.
@rainersigwald do you have a quick example of what an msbuild format for a solution might look like?
I thought it was merely for VisualStudio but at build time it would pass the relevant csproj files down to msbuild, and that msbuild only deals with those.
The reason it's more complex than that is that VS builds individual projects with configuration derived from the solution. That enables the things you can do with the Solution Configuration Manager, like "don't build this project in this configuration" or "when the solution is in Release configuration, still build this individual project as Debug". See MSBuild's AssignProjectConfiguration
task for a bit of the code required to deal with this.
do you have a quick example of what an msbuild format for a solution might look like?
I do not, in large part because one of the sources of complexity here is that I don't know all of the configuration capabilities of the .sln format. I learned a new one yesterday investigating https://github.com/Microsoft/msbuild/issues/626#issuecomment-282117160! Building all of the capabilities of the current format into a new one is one reason this has been put off for over a decade (the other big reason is that the solution-handling code in VS is ancient and has tentacles into lots of things, so it's not easy to drop in a replacement).
we should still strive for it.
I agree, and I think everyone agrees in principle--I haven't met defenders of the current format. It's just a matter of prioritization.
As @rainersigwald says, this has been put off repeatedly and it really is something for the VS team to drive as they would do almost all the work (since it's safe to assume they would move to a format that MSBuild already understands)
Although the solution has tendrils throughout VS, to my knowledge, knowledge of the solution format is pretty localized (as you would hope) so changing the format should not be a huge effort.
Next decision to make would be how VS would handle changing the build process of a solution. Right now you can't do that or at least VS will ignore it: it invokes MSBuild individually on each project in the solution -- it does not "build" the solution itself, as MSBuild does. Lots of parts of VS listen to events through the build of all the projects and if the build process changes, they might get confused about that. (They don't generally pay attention to what happens within the build of a particular project, so this would be a new issue.)
However they may want to go further. MSBuild doesn't care what your project structure is, it can be n-level for example. VS doesn't work quite the same when you reference projects that aren't listed in your solution; it doesn't represent visually any kind of hierarchy or structure beyond 2 levels; solution folders are fake folders. So if VS wanted to invest in the solution file, they might want to think beyond just changing the format of the file and instead allow VS to just open any number of random MSBuild files at once and make some sense of it.
+1 for a native MSBuild format. It would be awesome to have it as "simple" as
<Project Sdk="Microsoft.Sln.Sdk">
<ItemGroup>
<SolutionProject Include="**\*.*proj" />
</ItemGroup>
</Project>
Since this seems to be more of a long term goal, perhaps in the meantime we can make surgical improvements to the existing format.
Can anyone explain/confirm if 1) type Guids are not needed/can be inferred 2) VS version information is not needed
I got exactly the same question, will we have a human-ready sln format?
SLN currently has that archaic syntax. GitHub linguist classifier even doesn't understands it.. was it vb, inf, ruby or which language was the source of inspiration back in 1900-who-knows. Dotnet-cli team had to create a custom parser and writer to add support for dotnet new sln
-- actually took from Mono: https://github.com/dotnet/cli/blob/b674f5d/src/Microsoft.DotNet.Cli.Sln.Internal/SlnFile.cs
XML is something used in
So if VS wanted to invest in the solution file, they might want to think beyond just changing the format of the file and instead allow VS to just open any number of random MSBuild files at once and make some sense of it.
@danmosemsft, since we don't have any idea whose scones to butter to make it ever happen, but we would stand by you and vote if you further this discussion with right people in VS team. If they just start with the drop-in replacement of SLN for vNext of VS that understands everything what current SLN provides today, it would improve a lot!
Once that gets shipped and both VS and MSBuild get familiarized with this format, they can add exciting new features "stuff that wasn't possible with old format".
Or VS guys can open source their core solution handling module to enter the community-driven-development bliss.
This idea is listed in the Visual Studio User Voice. Vote for it.
I know that only some of the information is written, depending on the (solution) configuration and platform selected, but the output seen with MSBuildEmitSolution when using MSBuild might be a place to start. Obviously the information in there would need to be generated by the Microsoft.Sln.Sdk
if it wasn't present in the file directly, and as some of it is proxy targets for individual projects, it might need to be generated and cached (maybe like the nuget project.assets.json?)
I for one would love there to be something like
<ItemDefinitionGroup>
<SolutionProject>
<Configuration>$(Configuration)</Configuration>
<Platform>$(Platform)</Platform>
<SolutionConfiguration>$(Configuration)</SolutionConfiguration>
<SolutionPlatform>$(Platform)</SolutionPlatform>
<SolutionDir>$(MSBuildThisFileDirectory)</SolutionDir>
<Build>True</Build>
</SolutionProject>
</ItemDefinitionGroup>
In the defaults which would allow overriding on a per project basis, and all project metadata to be passed to the project build.
And maybe even a nice project globbing pattern based on installed languages / extensions.
I have more use cases here that a MSBuild format would make possible! For example, take a look at MiniProfiler: https://github.com/MiniProfiler/dotnet. It's a library that supports ASP.NET Core and non-Core (new and old) versions. Now because of that, I need sample projects for both. So the solution contains a sample for ASP.NET and a sample for ASP.NET Core, for the people, you know, the lovely people! They like samples. They're good folk.
Now, a use case! The dotnet build
tooling does almost everything you'd want here to build a solution. But, since dotnet build
cannot build a ASP.NET non-Core sample, it throws an error every time (which error doesn't matter, it's not supported and that's not the point of this comment). Also, AFAIK, you cannot filter what would be built, aside from carrying the baggage of additional build configs just for packaging...which is a bad state to be in when testing vs. deployment.
If the .sln
file (I'm gonna lobby for .slnx
here!) was XML/MSBuild, I could do something as simple as /p:IncludeSamples=false
around a <Projects Condition="$(IncludeSamples) == 'true'">
section (like proposed in the original issue) to exclude them. Any configuration could be treated this way really. I'm not saying that's an easy task, but it would be a huge usability and versatility improvement to build a solution however you wanted.
Plus, ya know, no GUIDs because ewww.
@NickCraver Would something like https://github.com/Microsoft/MSBuildSdks/tree/master/src/Traversal be what you're looking for?
Seems like that would be a good model for what solution files should end up being.
I believe in VS organization, the team owning SLN would have more context on full list of supported verbs and variation.
Lets assume there is no team, folks who invented SLN two decades ago left and nobody is maintaining it anymore.
Then here is a #Hackathon idea for @karelz:
Implementation of new format can be done and validated against 3 million SLN files on public GitHub https://github.com/search?q=fileextension%3Asln+project. A cronjob can be written to collect distinct verbs/tokens from 3M files. For parsing, we can use https://github.com/dotnet/cli/blob/b674f5d/src/Microsoft.DotNet.Cli.Sln.Internal/SlnFile.cs.
I think if it still misses some obscure verb for example that was only supported in past century VS 97, it is most likely acceptable.
With GitHub v3 API, it is bit more work. First it needs to traverse through organizations:
https://api.github.com/search/code?q=extension:sln+org:dotnet
then call:
https://api.github.com/search/code?q=extension:sln+org:$ORGANIZATION
to get url
value, navigating to which gives us download_url
.With 100 threads it will take 30K iterations.
Once there is an exhaustive list, an XML schema can be established, which someone in VS team can implement with 5-10 lines of C# code to replace archaic SLN syntax.
@NickCraver a workaround you could use for your case today is to customize MSBuild's view of the solution when it builds from the command line (as in dotnet build
).
You can do this with a solution build customization. Since your solution is MiniProfiler.sln
, create a file named after.MiniProfiler.sln.targets
that manipulates the ProjectReference
item before MSBuild starts building things:
<Project InitialTargets="RemoveIncompatibleProjectsFromDotnetCoreBuild">
<Target Name="RemoveIncompatibleProjectsFromDotnetCoreBuild"
Condition="'$(MSBuildRuntimeType)' == 'Core'">
<ItemGroup>
<!-- These projects don't successfully build in `dotnet build`, so don't build them
when MSBuild is running on Core. -->
<ProjectReferenceToAvoidInDotnetBuild Include="samples\Samples.Mvc5.EFCore\Samples.Mvc5.EFCore.csproj" />
<ProjectReferenceToAvoidInDotnetBuild Include="samples\Samples.Mvc5\Samples.Mvc5.csproj" />
<ProjectReference Remove="@(ProjectReferenceToAvoidInDotnetBuild->'%(FullPath)')" />
</ItemGroup>
</Target>
</Project>
@bording @rainersigwald Thanks! I'll give both of these a look today and see what works. Traversal does seem to be the more appealing option if it works. I'll give it a shot and report back :)
@bording Unfortunately I hit issues with Traversal but indeed that's very appealing. I filed an issue with what I hit; maybe I can help resolve this one given I have an easy (I think) repro: https://github.com/Microsoft/MSBuildSdks/issues/34 I'm not sure if this points to a larger issue of tree traversal shenanigans that currently happens via .sln
resolution of what to build or not.
@NickCraver .slnx
reminds me of .doc
-> .docx
, not in a good way. .slnproj
is the way to go.
A noticeable thing is that if I move a project file's position, project references with GUID will automatically correct its position, seems using GUID from the solution. But I think Visual Studio should has a feature to move a project and correct references together.
@rainersigwald so the last info on this is paraphrased "we're not in charge to decide this" - which is totally fine. But can we at least know who is, maybe a link to uservoice if its directly decided by the VS programm ownership.
Also: Maybe we can do this in two steps? Lots of negative feedback for SLN has to do with the large amount of GUIDs in the sln file. Maybe (as the GUID went away from regular projects) we can make an effort to get rid of the GUIDs first and then proceed with the big one in a larger timeframe?
I made an sdk-style msbuild solution file format, the use is limited since there is no VisualStudio support, but it can still be used with vs code, Visual Studio Open Folder or build-only solution.
https://github.com/JeffCyr/MSBuild.SolutionSdk
A solution file can be as lean as this:
<Project Sdk="MSBuild.SolutionSdk/0.0.2" />
By default, all csproj/vbproj/fsproj/vcxproj under the folder hierarchy of the solution file will be included in the solution. For simple solutions, the .slnproj file may never have to be edited again.
@JeffCyr there's a ms-built version at https://github.com/Microsoft/MSBuildSdks/tree/master/src/Traversal that does that same you are doing but also covers some more edge cases (but is certainly less user-friendly / documented and lacks default items)
<Project Sdk="Microsoft.Build.Traversal/1.0.43">
<ItemGroup>
<ProjectReference Include="src\Common\Common.csproj" />
<ProjectReference Include="src\App\App.csproj" />
<ProjectReference Include="src\WebApplication\WebApplication.csproj" />
</ItemGroup>
</Project>
@dasMulli Indeed, Traversal seems great for creating a simple build script. The main difference with MSBuild.SolutionSdk is that it tries to keep the same experience as current sln files with configuration management and build dependencies. My hope is that this project can serve as a playground to eventually be standardized and replace sln files in Visual Studio.
With the new msbuild Sdk pluggability, the solution proposed above by @JeffCyr and the related MSBuildSDKs/Traversal initiatives are exactly where msbuild sln should go.
I would love to see this adopted. There is the IDE integrations story (VS, VSCode, Rider...etc.) but the opportunities/scenarios offered by such a solution (😅) are just tremendously exciting!
Is there any plan to prioritize this work? cc: @davkean @KirillOsenkov
I still routinely hit issues where someone forgot to commit changes to the sln, or there are merge conflicts. I was hoping this would be tackled for VS19, but doesn't seem to be the case.
Is there anyone that could champion this and bring it up with the VS team or whoever is responsible?
Would this be a good candidate to tackle for the .NET 5 timeframe?
Pretty please
This has been put off for almost 15 years now, so I'm pessimistic--but it's a totally reasonable request, and maybe now is the time it can actually get done.
@rainersigwald 3 years later the situation seems to be unchanged, has the chance of this happening increased or decreased?
It's the second most :+1: issue here, only surpassed by #613. The UserVoice someone linked no longer exists. What can we do as customers to give this request a higher priority?
Since the uservoice site apparently is gone and I wasn't able to find a relevant issue for this on the new https://developercommunity.visualstudio.com/ I've gone ahead and created a feature request there: https://developercommunity.visualstudio.com/idea/988209/clean-up-sln-visualstudio-solution-files.html
Please upvote it just in case it helps get the relevant parties more aware of this.
I never understood why Microsoft created Solution files in the first place. A solution file should just be a .csproj file containing references to child .csproj files. Configuration data is cascaded down from down the hierarchy with each .csproj having the ability to override it's parent configuration in the same way .config files do. This would make configuration a lot easier than it is now.
I never understood why Microsoft created Solution files in the first place.
Sln files predated csproj and predated building without using VS so the format probably wasn’t considered too important at the time. That said they could have made them more mergeable.
@Joebeazelman To echo @danmosemsft there are several other project types out there beyond CSPROJ; for example our use case has the following project types:
Historically not all of these types were "MSBuild Native", but the last big Microsoft hold out (VCPROJ) I believe was converted in either VS 2012 or 2013?
We're not huge fans of the format, but honestly there are other places our company would like to see development resources placed (for example getting all of the classic Project Formats converted, or improving project load times for large solutions (1000+ Projects).
I'm a bit curious why you require 1000+ projects? I can somewhat understand getting into the lower 100s, but even then I would seriously considering splitting things up, but literally 1000s?
@chrisaut The system is a huge monolith from 35+ years of code; its wild! Here's a gist of one of the dependency trees https://gist.github.com/aolszowka/a93ea5545d54344c61f66830fae90c4e its a dotgraph generated using https://github.com/aolszowka/MsBuildProjectReferenceDependencyGraph. Use GraphViz (takes around 10-15 minutes on my workstation to generate) don't bother with WebGraphViz it'll choke.
I really wish this wasn't the case but attempting to pay off this technical debt is going to take a long time (I'll probably be long gone!).
Most projects, even with their minimal dependencies end up floating around 200-300 projects.
@Joebeazelman @danmosemsft @chrisaut Sorry to double post, but I thought I should reply to this comment:
That said they could have made them more mergeable.
It would be really cool if Visual Studio sorted these out of the box, a long time ago (way back when we had Microsoft Connect instead of Developer Community) there was an ask to have them sorted alphabetically. I do not believe it made the jump to Developer Community.
As a stop gap I opened sourced a bunch of our tools to manage these files (we have something like 5,000+ Solution files). I really wish we could trash every single one of these and just use stuff out of the box, but thought I'd be worth sharing:
All of these tools are MIT Licensed/Open Sourced, it'd be super cool if they were integrated somehow into VS and we could delete them, until then our recommendation is to throw them in CI, otherwise you will drown trying to keep them all up to date.
@aolszowka thanks for sharing!
@Joebeazelman To echo @danmosemsft there are several other project types out there beyond CSPROJ; for example our use case has the following project types:
- VCPROJ
- VBPROJ
- SQLPROJ
- SYNPROJ
- WIXPROJ
Historically not all of these types were "MSBuild Native", but the last big Microsoft hold out (VCPROJ) I believe was converted in either VS 2012 or 2013?
We're not huge fans of the format, but honestly there are other places our company would like to see development resources placed (for example getting all of the classic Project Formats converted, or improving project load times for large solutions (1000+ Projects).
I would've left those project formats alone and used PROJ for all future MsBuild Native formats for Visual Studio and MSBuild. One single format for any language.
As a side note, I hope you guys don't adopt YAML in the future. Developers, such as myself, can only handle so much cognitive load. Please use our remaining bandwidth judiciously on something that's a clear improvement in terms of productivity.
As a side note, I hope you guys don't adopt YAML in the future.
@Joebeazelman Right there with you. I think though, based on the fact that GitHub Actions are all YAML based, we might be out of luck!
I would've left those project formats alone and used PROJ for all future MsBuild Native formats for Visual Studio and MSBuild. One single format for any language.
As Raymond Chen often says:
Many decisions make sense only in the context of history.
https://devblogs.microsoft.com/oldnewthing/20110119-00/?p=11723
All of those projects are first class citizens in the Visual Studio Ecosystem. While lots of progress is made here https://github.com/dotnet/project-system its a really big ship with lots of players.
Interesting Twitter thread by @davidfowl
" Feels like it’s time for a .NET tooling renaissance.Solution files are dated, and project files while much cleaner, are tied to the powerful but flawed msbuild. We’ve seen huge performance improvements in runtime performance but haven’t done the same on the tooling side. #dotnet "
.NET 6 is being planned out ATM. I can't help but wonder if, as part of it, perhaps a tiny bit of at least thought could be given towards this sln mess? Or is it not on the radar at all?
Solution files are not just for .NET, there are many other project types. Probably, it should be considered for the next major version of the Visual Studio.
Understood, but someone needs to push for it.
VS still understand the old csproj file format along with the new, we need something similar for solution files, even if at first it only supports a small portion of all the features of the current sln format.
.NET is in a unique position to push for this IMO.
It was also my time to need this so badly right now.
It would be great if this task finally gets prioritized. In the mean time I had to quickly find a workaround to generate a Solution on Linux platform so I came up with a quick powershell script that can create a .sln file from a given template. It's very simple and it supports only generating a solution with Release
/Debug
configurations and a given platform (for example x86
/x64
). It doesn't specify dependencies but implicit dependencies are respected anyway. Projects can enforce a different platform, for example Any CPU
. The script with an example is available as a gist at this address.
@ceztko for generating solution files I recommend slngen which is available as a global tool.
for generating solution files I recommend slngen which is available as a global tool.
Interesting! I was missing such tool. I just tried: while not entirely clear from the documentation it can also work with a list of projects as arguments. For sure I will consider it.
slngen uses built-in file globbing, similar to msbuild. Which means, it also works with space separated paths and shell globbing.
# bult-in globbing
$ slngen '*/*proj' -o Main.sln
# shell (bash) globbing - without single quotes
$ slngen */*proj -o Main.sln
# space separated paths
$ slngen src/foo/foo.proj src/bar/bar.proj tests/baz/baz.proj -o Main.sln
if we drop -o
argument, it will generate sln files for each project. The tool name (Microsoft.VisualStudio.SlnGen.Tool
) is a bit unconventional, one would expect dotnet tool install --global slngen
(or dotnet-slngen
).. but those are the minor details. :)
Since nothing was explicitly mentioned, I assume no work is planned here for VS2022 either?
It's really a shame. At least we get new icons to look at while we fix merge conflicts, so it's got that going for it I guess.
More than 5 years have passed already since this issue was open and I wish this could be prioritized.
Every single time projects gets added in different branches in our solution, merge conflicts appear and inevitable one of the projects gets temporarily lost, until it gets discovered that it was left out during the conflict solving.
That's because this is a HARD problem, a really hard one. We should tackle it but solution files have tentacles everywhere and we need a real plan for how to replace them. Any plan that contain the words "just" isn't a plan 😄. I mean a real well though out plan that discusses the multi year migration plan for .NET projects and C++. Having personally introduced a new project system into the .NET and Visual Studio ecosystems I know how painful it is.
Don't get me wrong, we should do this, but we haven't spent the brain power to come up with a feasible solid plan AFAIK.
From @chrisaut on February 21, 2017 4:32
Now that the csproj files are
somewhat
clean, are there plans to similarly clean up .sln files?A sample solution with just two projects looks like this today:
I see 3 "sections": 1) Information about VS, which version created it and the minimum version 2) List or projects and their locations 3) Solution and ProjectConfigurationPlatforms
1) Is the VisualStudio stuff really needed? I regularly run into changes here when opening solutions in different versions, it creates a change for no apparent reason.
2) Can we get rid of the GUIDs for the project lists? Also the logical name (coreDemo, netStdLib) in addition to the csproj, can this just be infered for the probably 99.99% case when the two match?
3) I can't say much about the ConfigurationPlatform stuff, except that it looks messy. I feel like this should be pulled out somehow.
Since everything is going xml (....I know, I know), perhaps the format of the sln file should also be xml. A minimalistic solution could look something like this:
A few things to note: The Project Type Guids ("FAE04EC0-301F-11D3-BF4B-00C04F79EFBC", at least that's what I think those are) are messy, if this is really needed by VS for some reason let's please make it a string that makes sense for humans ("netCoreConsole" in the example). We pull the ProjectConfigurations into the projects where they logically belong. Also, while at times custom platform/configurations are needed, most of the time people I think just use the default (x86/x64/Any CPU)/(Debug/Release). So we just make those the default. For the project list we could also do the filepattern thing (*/.csproj) but I feel like projects aren't added/removed often enough to warrant this, so perhaps being explicit here is the better choice.
I just want to start this issue so that a discussion can be started, I'm by no means an expert on this stuff.
Copied from original issue: dotnet/roslyn-project-system#1594