microsoft / slngen

Visual Studio solution generator
MIT License
357 stars 76 forks source link

Allow defining project dependencies. #321

Open tokizr opened 2 years ago

tokizr commented 2 years ago

Hello.

In my company's projects we now have a few native libraries that are wrapped by CppSharp, and that requires dedicated projects to setup the bindings. We'd like to add dependencies to those projects so they build order is correct.

This is possible with the ProjectDependencies section:

Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NativeWrapper", "NativeWrapper.vcxproj", "{WRAPPER-GUID}"
    ProjectSection(ProjectDependencies) = postProject
        {BINDING-GENERATOR-GUID} = {BINDING-GENERATOR-GUID}
    EndProjectSection
EndProject

Currently it seems it is not possible to generate this information with SlnGen.

jeffkl commented 2 years ago

The project dependencies section of a solution file has always been a point of contention. If you only specify build order in a solution file, there is no guarantee that projects will build directly. I'm not opposed to adding this functionality to SlnGen since it exists in solution files themselves, but I would recommend you don't use project dependencies at all. Instead, you can add ProjectReference items to projects that depend on this VCXPROJ and set appropriate metadata so that you only have a build-time dependency and that's it.

<ItemGroup>
  <ProjectReference Include="..\NativeWrapper\NativeWrapper.vcxproj"
                    ReferenceAssemblyOutput="false"
                    SkipGetTargetFrameworkProperties="false" />
</ItemGroup>

SlnGen would generate the same solution but MSBuild and Visual Studio would always build NativeWrapper.vcxproj first, making it possible to build a project or a solution correctly.

https://docs.microsoft.com/en-us/visualstudio/msbuild/common-msbuild-project-items?view=vs-2022#projectreference

tokizr commented 2 years ago

I totally agree that this should be solved in the projects themselves, and that's exactly the first thing I tried, however we ran into issues with this approach:

  1. We have two solutions, one that contains native projects (and is built in VS) and other that's built using the dotnet SDK (and does not contain the native projects). The Visual C++ SDK is not available when building with dotnet so it fails with Imported project "/Microsoft.Cpp.Default.props" was not found.
  2. This does not work in the other direction, .i.e.: the same trick in the .vcxproj does not work (dependency even shows in vs but build order is not affected).

We can work around # 1 by making the dependency conditional, but that was far from perfect; And I could not get a workaround in place for # 2.

For that reason it seems to me the simplest solution is to instead use the build dependency system in the sln file.

JeremyMorton-Blizzard commented 6 months ago
  1. This does not work in the other direction, .i.e.: the same trick in the .vcxproj does not work (dependency even shows in vs but build order is not affected).

It seems like a ProjectReference in a .vcxproj needs the Project set to the referenced project's GUID to get VS to treat it a build dependency, for example:

    <ProjectReference Include="..\Foo\Foo.vcxproj">
      <Project>{BB3995C0-27EF-0DB6-B0E3-078D1C9804BA}</Project>
      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
    </ProjectReference>