Skip to content
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

Real support for shared projects (shproj/projitems) #2511

Open
thomaslevesque opened this issue Sep 2, 2018 · 21 comments
Open

Real support for shared projects (shproj/projitems) #2511

thomaslevesque opened this issue Sep 2, 2018 · 21 comments
Milestone

Comments

@thomaslevesque
Copy link
Member

What's the current story for shared projects with the .NET Core SDK?

I can create a shared project in VS, and reference it from my .NET Core project, but the experience is far from ideal. The shproj is an "old-style" project, where source files are explicitly included. I can use glob patterns, but when I add a new file from VIsual Studio, it's added explicitly to the project, which causes it to be included twice.

Is it possible to make a real .NET Core shared project ?

@pipe01
Copy link

pipe01 commented Feb 20, 2019

Any updates on this?

@Phyyl
Copy link

Phyyl commented Aug 19, 2019

I would also love to know if there are any developments on this. If I can be of any help too!

@markusschaber
Copy link

Almost two years now without any reactions :-/

@msedi
Copy link

msedi commented Jan 9, 2021

I would also be interested what the current status is?

@dasMulli
Copy link
Contributor

dasMulli commented Jan 9, 2021

I guess that's more a project system issue than a .NET SDK issue. The SDK has tests assuring that both shared projects and "deploy projects" (referencing SDK project but wihout any own comiplation) work.
VS support is more interesting here I guess - cc @davkean
Then SDK commands could also have some knowledge about shproj.. the difference is that these aren't technically project references but includes

@VAllens
Copy link

VAllens commented Nov 3, 2021

Are there any plans to support it?

@sharpjs
Copy link

sharpjs commented Jul 6, 2022

I've been using Microsoft.Build.NoTargets for SDK-style shared/just-a-bunch-of-files projects.

@commonsensesoftware
Copy link

I might wrong, but other than Visual Studio forums, I think the only other place we might voice an option is:

https://github.com/microsoft/VSProjectSystem

I don't see any mention of shared projects there. The Shared Project System is closed source (to my knowledge). There probably isn't all that much work to get this done, it just has to be prioritized.

Microsoft.Build.NoTargets does work well for loose files, there are some features lacking from a Shared Project. If you just need miscellaneous files, it's a good choice. If you have arbitrary source code files, which should honestly be pretty rare in my experience, it also works well, but you still have to link the files.

I'm not sure why the project system doesn't exclude these in its targets by default, but I find it annoying that unnecessary or usable files appear in content-only type project of loose files. The following will hide it from Visual Studio, if you care.

<ItemGroup>
  <None Include="**\*.*" Exclude="*.msbuildproj;obj\**\*.*" />
</ItemGroup>

I have several projects that multi-target and I find Shared projects the most useful and functional experience in Visual Studio to share code. The issues all stem around the UI experience. You can manually edit the *.projitems file as follows to get the .NET SDK style type MSBuild experience:

<ItemGroup>
  <Compile Include="$(MSBuildThisFileDirectory)**\*.cs" />
</ItemGroup>

Inside *.projitems

You only ever have to do this once. The problem is what the project system tries to do afterward. All my attempts at adding or removing files via Solution Explorer will cause things to go haywire. The only solution I've found is adding the files directly to disk, if not just an empty file. Once visible in the project, you can edit it just like any other file. The Shared project will pick up the files, but you may not see it in the Solution Explorer right away. Any of the following should remedy that:

  • Unload/Reload the Shared project
    • This would be a lot easier if VS still had macro support
  • Show all files
  • Restart Visual Studio

@commonsensesoftware
Copy link

I took the liberty to create a Visual Studio feature request:

https://developercommunity.visualstudio.com/t/Support-NET-SDK-Style-Behavior-in-the-S/10221992

If we really want to get it added, everyone needs to vote and spread the word. The program management team prioritizes what to work on based on features with the most votes.

@VAllens
Copy link

VAllens commented Dec 6, 2022

I took the liberty to create a Visual Studio feature request:

https://developercommunity.visualstudio.com/t/Support-NET-SDK-Style-Behavior-in-the-S/10221992

If we really want to get it added, everyone needs to vote and spread the word. The program management team prioritizes what to work on based on features with the most votes.

good

@dsplaisted dsplaisted added the needs team triage Requires a full team discussion label Jan 4, 2023
@marcpopMSFT marcpopMSFT removed the needs team triage Requires a full team discussion label Jan 4, 2023
@marcpopMSFT marcpopMSFT added this to the Backlog milestone Jan 4, 2023
@marcpopMSFT
Copy link
Member

Moving to the backlog. At the time, we are not planning on prioritizing this. Our recommendation today is to put the shared files in a folder and use globbing in the consuming projects.

@commonsensesoftware
Copy link

@marcpopMSFT that works for VS Code, but is completely unusable in VS with a solution. Using "Open Folder" in VS is not a like-for-like alternative and causes a lot of churn in solution files. Using globbing patterns is hardly a substitute for what a Shared Project brings. Linking files with globbing patterns as you've suggested was one of the only methods to achieve this before Shared Projects were introduced. I can say from that experience that managing things that way is PITA. If Shared Projects themselves honored globbing without a ton of manual editing and/or reloading, that would be a great step forward.

As an advanced MSBuild user, I understand how to link and share files from other sources. Most people, however, do not have this experience nor understand what is necessarily required to make things work. Case in point, I wouldn't expect the example you referenced to work as expected. It illustrates linking <Content> and not <Compile>. This is the type of landmine that people who are not MSBuild experts step on.

There isn't anything super magical about Share Projects. If there were future state where this particular project system were open-sourced there are people in the community that would contribute. Since all the inbox project systems are closed source, it makes it difficult to move the needle.

@marcpopMSFT
Copy link
Member

My understanding from @dsplaisted was that shared projects were created during the UWP efforts and before we had sdk-style projects with improved globbing support. If we updated our documentation to include a <Compile> example as well, do you think customers without deep msbuild knowledge would be able to use that plus globbing to get the experience you're trying to achieve? The project system with sdk-style projects is supposed to handle globbing with compile much better than before. We could potentially improve that experience if there were specific gaps which might be better than trying to add shared project support.

@msedi
Copy link

msedi commented Jan 5, 2023

I had the same problem a while ago, but with a bit more requirements on this.

Couldn't we simply use <ProjectReference> and extend it with an additional property (e.g. Merge="True")? Maybe with the possibility to change the access (internal, public, private, file). The effect should be that the "code" is merged into the current/including assembly.

A similar thing could be done with <PackageReference> and with <Reference>.

@commonsensesoftware
Copy link

commonsensesoftware commented Jan 5, 2023

@marcpopMSFT thanks for continuing the conversation.

Yes, Shared Projects were introduced during the UWP efforts, but this was really because prior to MAUI, multi-targeting, especially UI apps, was really painful. For those of us doing multi-targeting all the way back to the PCL (Portable Class Library) days, you know the pain. The very first time I saw the Shared Project system (yes it was for UWP), I was like "Finally! A first-class way to separate and link files without globbing miscellaneous files from the file system".

The biggest problem with proposing just using a globbing pattern with the source files is how the source files themselves are managed. Visual Studio only deals with virtual solution folders. Yes, you can "Open Folder", but that's some else entirely and comes with a different set of problems. You can't just have a folder of loose files without creating solution folders and explicitly including them; globbing isn't any option. This causes a lot of churn in the solution. You can choose to just use folders on disk and reference them by way of globbing pattern (etc), but this is a very subpar coding experience; especially in a robust IDE like VS. VS only knows how to deal with projects, even if what you need is not a project and just a loose collection of files.

The Common Project System (CPS) really helped solve a lot of things and made it way easier to light up project system variants (for those that don't know). When combined with the SDK-style project approach, it's even better. It would seem that the Shared Project system just missed when that became available. Some of the advantages you get from a Shared Project is the TFM dropdown when you multi-target. This is immensely useful when writing code, refactoring, and debugging. Fortunately, CPS subvariant can and do retain this functionality.

The current, closest replacement to Shared Projects is the No Targets SDK subproject type. It mostly does what you would want from a Shared Project, including better globbing support. It doesn't, however, come without its own problems - namely:

  1. You have to create the project file by hand (e.g. create the XML manually)
  2. The file extension must be *.msbuildproj or Visual Studio doesn't know what to do with it
    a. MSBuild doesn't care; the file can have any extension, including no extension at all
  3. The *.msbuildproj file and obj are not hidden by default
  4. Add → Class... is not available
  5. Add → New Item... yields no item templates
    a. This typically means you have to create the files on disk externally or copy/paste a file

These are all solvable problems, but the onus is largely on the developer. Here's an example of a working project:

<Project Sdk="Microsoft.Build.NoTargets/3.3.0">
  <PropertyGroup>
    <!-- required, but completely meaningless -->
    <TargetFramework>netstandard1.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <!-- don't show the *.msbuildproj and obj in Solution Explorer; Show All Files will still work -->
    <None Exclude="*.msbuildproj;obj\**\*.*" />
    <Compile Include="**\*.cs" />
  </ItemGroup>
</Project>

This is far from ideal, but is a workable solution. It's certainly better than just loose files.

There still some know-how for less savvy MSBuild users. At some point, "You must be at least [this] tall to ride the [ride]." 😛 I know you can't just commit to it, but in an ideal world, I could see either the No Targets project system or a new Include Files Project system created out under the MSBuild SDK repo as OSS, paired with a project template, and made a first-class, inbox option when adding new projects in VS. I'm sure retaining VB.NET parity would be feasible too. The commitment by you and your team would ultimately be to sign-off of the validity of the template(s) and take care of the bureaucracy to include it with a future VS release. If we were to meet in the middle and meld minds, I think it would this issue to be once and for all.

@commonsensesoftware
Copy link

@msedi I'm not sure I follow. What you are proposing is exactly what a Shared Project already does. If you want to propose a change to the way build works, then you probably want the MSBuild repo. The Shared Project system is closed source so I get that it is confusing as to where you can voice your opinion about it (though it's usually the VS Forum). This issue is specifically about enhancing/replacing the Shared Project feature without changing MSBuild.

@sharpjs
Copy link

sharpjs commented Jan 6, 2023

2. The file extension must be *.msbuildproj or Visual Studio doesn't know what to do with it

I have not experienced this problem. I've used .csproj and even just .targets* for my projects using the NoTargets SDK.

* Yes, I had a valid reason to do that. Here is an example.

@commonsensesoftware
Copy link

@sharpjs I haven't tried *.csproj ('cause it's not actually a C# project), but I'll just go out on a limb and say that you're correct. The file extension for the project has nothing to do with MSBuild and everything to do with Visual Studio. You can't Add Existing Project... without it being one of the supported extensions:

image

*.msbuildproj generically maps to all CPS project subtypes. I'm curious how you got your .root.targets included as a project. I presume you edited the solution manually because I see {9A19103F-16F7-4668-BE54-9A1E7A4F7556} in the solution file, whereas a CPS normally has {13B669BE-BB05-4DDF-9536-439F39A36129}. I have no qualms about that; however, this is more advanced sorcery 🧙🏽‍♂️ that mere mortals don't typically know about. 😉

My argument(s) are purely advocating for those that don't know how to do these things. The vast majority of developers who find themselves in this situation or landing on this issue have a simple requirement: "I just want some loose C# files that I can see in the Solution Explorer and then reference them in one or more C# projects." Dealing with the limitations in Shared Projects and/or No Targets gets you pretty close.

I commonly use No Targets for build extensions as they are loose files that don't compile or even get referenced. In days gone by, the you either had to create your own equivalent, add them to a solution file, or deal with them by opening them via File Explorer (etc).

@sharpjs
Copy link

sharpjs commented Jan 6, 2023

. I'm curious how you got your .root.targets included as a project. I presume you edited the solution manually

I first named it .root.csproj and used Visual Studio to add it to the solution. Then I edited the solution file manually, renaming to .root.targets.

The reason for the .targets extension is to hide the file from the dotnet command. I want dotnet build to find only one project-or-solution file (the .sln) in that directory. Otherwise, I would need to specify the .sln file explicitly in every invocation of dotnet. The use of the .targets extension preserves IntelliSense in Visual Studio.

@marcpopMSFT
Copy link
Member

Thanks for the detailed replies. I think I understand a bit better about the limitations you're seeing in the current experience and why you are looking for improved support here.

If you want shared files showing up in solution explorer outside of a project, you can do that but you have to manually manage the list in the solution file. I think we can all agree that the solution file experience isn't great. Here's how we do it in the SDK repo:
https://github.com/dotnet/sdk/blob/main/sdk.sln#L6
image
With this experience, you do get some amount of add functionality.

Alternatively, you can use globbing and LinkBase as I suggested above similar to what we do here:
https://github.com/dotnet/sdk/blob/main/src/Tasks/Microsoft.NET.Build.Tasks/Microsoft.NET.Build.Tasks.csproj#L85
image

As you noted, the drawbacks here are around the project system functionality like add don't work. So instead, customers are using the NoTargets sdk and creating their own version of shared projects that way which I believe works fine but it just more complex.

Is the above summary roughly accurate? I don't think the project system is investing further in shared projects as those were specifically created for UWP but perhaps we can use your dev community ticket to outline some of the gaps that exist in the add class/new item experience. If that experience were improved to support the add behavior, that might be enough for most customers to not have to resort to one of the other options covered above. I'll add some details internally to the dev community ticket and talk to our friends on the project system team.

CC @kvenkatrajan

@commonsensesoftware
Copy link

@marcpopMSFT I'd say you just about nailed it IMO. ASP.NET API Versioning started using No Targets to solve the same build extension management in the solution you have:

image

Aside from the items listed above, the only other issue I see is discoverability. No Targets isn't a pure drop in replacement for a Shared Project because the name is not obvious and it's not included inbox. If you're working in a disconnected environment, say on a plane, you cannot (currently) create a No Targets project the same way you can a Shared Project because it requires a connection to NuGet. A project template included with VS could remedy both of those.

Thank you for being customer obsessed! 😉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests