Can I use MSBUILD scripts to replace SLN files?

2019-08-10 07:28发布

问题:

I would like to move my builds from using Visual Studio SLN files to using MSBUILD sripts (we're approaching 100 projects in the SLN file), but I don't want to dual-maintain the SLN files for when we're editing code within Visual Studio.

What I would like is to create a dependency-tree of MSBUILD scripts, and then be able to select any one MSBUILD script from Visual Studio to use as if it were the SLN file - including all dependent projects automatically.

Can Visual Studio do this? Are there any existing tools that can dynamically create SLN files from MSBUILD scripts? Has anybody tried to write a tool to do this?

回答1:

It should not be too hard to create something like this as long as you rely on referencing projects (as opposed to compiled dlls) and if you have some Xml experience. You would parse the initial csproj file (which is Xml) and read all the references to the projects. They look something like this:

<ProjectReference Include="..\..\src\Test\Test.csproj" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Project>{ab709f59-aa17-4297-b827-101d086586e1}</Project>
  <Name>Test</Name>
</ProjectReference>

As you can see you have got path to the related csproj file. You would collect all the paths to related projects and do the same for each of these recursively until you process all files (be careful with projects referenced from mutliple projects (duplicates) - otherwise you will get into infinite loop). Note that csproj elements belong to non-empty namespace so you will need to take this into account when parsing Xml (.NET Xml APIs can handle these). You can collect all projects (paths, names, GUIDs) and then create the sln file or you can do it on the fly - each time you find a new reference.



回答2:

You can build your csproj as is, if you create an itemgroup of all your csproj and pass that to msbuild, the dependency order is determined for you (as longs a you have project references not dll references). Automajically.

Project references make for a slower build and you can have a much quicker build if you build using dll references but the tradeoff is that you have to know or determine the dependency order, and chaos can then ensure.

100 projects in an sln is a lot and will make you VS slow. I tend to have a sln per entity e.g website, web service rather than a monolithic build and sln.



回答3:

I wrote a tool that dynamically generates a *.sln file back in Dec 2011. Unfortunately due to politics here at work, I wasn't able to deploy it. We maintain over 600 project files for our build system, which is insanely too big for a solution. Well at least a solution you would actually try to load in the IDE.

Despite that, we do use a dynamically generated solution file that is loaded by MSBuild (Not Devenv.exe). No one ever tries to load that solution file in the IDE as far as I know.

Anyways, so the tool I wrote takes as a parameter the directory that contains our source code. It recursively searches and finds all the *.vcxproj and *.csproj files in it. Then for each project file it parses the file using the MSBuild API's. When it parses each file it looks for dependencies among the other project files. It is smart enough to find native dependencies for *.lib files. It is smart enough to find dependencies for managed c++/CLI which specify dependencies in the code file itself with something like: #using . It is also smart enough to find normal managed dependencies using assembly references. It also finds dependencies in a few other ways.

It then takes all those dependencies and generates a solution file. If you have questions feel free to ping me, and we can talk.



回答4:

I don't know of any existing tools. I know this perhaps doesn't answer your question directly, but I can just share my experience of working on large projects.

We've always split large solution files into a number of smaller ones of related projects. Then you can open one or two visual studios to see the projects you want to work on.

Then we have an msbuild script that builds each solution in turn to generate the entire product and installers.

No dynamic solution generation is needed. I'd worry that it might take quite a bit of work to maintain something like that, and also you'd have the situation where you're constantly working on different dynamically generated solutions so you never get to remember where things are. With a few fixed solution files, you can organize the projects into a few folders and then you've got some kind of organization in your head as to what goes where. With some decent organization, I find I only occasionally need to open and work on two solutions simultaneously.

We have one or more base/core solutions which contain projects with definitions that are shared between the other solutions. But, I haven't found it necessary to duplicate all the dependant projects from the base alongside the higher projects that use them. You can still debug your way through dependant projects without having them in the solution. If you do need to make a change, open the base solution and edit and build it and carry on.



回答5:

Have a look at GYP (Generate Your Projects), created for this purpose by Google (create project and solution files) and also to automate the build if necessary.

From their wiki:

GYP was originally created to generate native IDE project files (Visual Studio, Xcode) for building Chromium.

[..]

Also, some of the design of gyp was informed by experience at Google with large projects built wholly from source [..].

I currently use it when working with Chromium Embedded Framework, where it is used to generate *.vcxproj and *.sln files for Visual Studio 2012. In this case, it generates one solution file with 259 projects. It also generates *.vcproj files if using older version of Visual Studio.

As a side note, it's a nice way to keep project files out of the version control system and to quickly get a project setup for any new dev.

Edit: After reading again your question, I don't think you can generate *.gyp files from MSBUILD scripts, but it could still be worth the conversion effort.

Edit 2: Have a look at another answer which may also help, especially with gypfy.py which seems promising: https://stackoverflow.com/a/9387350/1412348