We have solution with a lot of projects and a more or less complex dependency graph between those projects. Now each of those projects should become its own nuget package and the dependency graph of the nuget packages should mirror the on of the projects.
I have two questions:
- Is it possible to achieve this while keeping all projects within the same solution? If so how?
- Is advisable to keep all projects in the same solution? What would be the a common / "best practice" approach to this?
The situation in our project is the same and we took the following approach:
The first step is to create the nuspec files defining your packages. We have placed all theses files in a folder named ".nuspec" which is located in the solution's root directory. The nuspec files are added to the solution in a solution folder that is named ".nuspec", too.
The solution itself has a global AssemblyInfo file that contains the versioning information as well as some copyright stuff - in short all information that is common between our projects. Each project then has its own assembly info adding the information specific to each project.
The nuspec files do not contain a version. Instead we use $(version)
as a placeholder there:
<?xml version="1.0" encoding="utf-16"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MyCompany.MyProduct.Server.DataAccess</id>
<version>$(Version)</version>
<authors>MyCompany</authors>
<projectUrl>http://example.com/myProduct.html</projectUrl>
<iconUrl>http://example.com/myProduct.icon.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Some description goes here.</description>
<summary>The summary goes here</summary>
<copyright>Copyright © MyCompany 2015</copyright>
<language>en-US</language>
<dependencies>
<dependency id="MyCompany.MyProduct.Common" version="$(Version)" />
<dependency id="MyCompany.MyProduct.Server" version="$(Version)" />
</dependencies>
</metadata>
<files>
<file src="path\to\MyCompany.MyProduct.Server.DataAccess.dll" target="lib\net45\MyCompany.MyProduct.Server.DataAccess.dll" />
</files>
</package>
(Of course the dependencies might have dependencies themselves. The server component might reference a logging component for example.)
Initially we created a console application reading the version of the solution from the global AssemblyInfo file and parsing it into all of the nuspec files before creating and publishing the packages.
The console application worked well, but was a bit tedious to maintain in a TFS environment with continuous integration enabled. So we defined a custom TFS build template doing this work. All we need to do now to create a set of nuget packages for all of our projects is to trigger a TFS build.
This approach has the advantage that all packages have the same version and thus work well together. This approach has the disadvantage that all packages have the same version and cannot be released independently.
We chose that approach because it prevented us from producing a conglomerate of badly integrated components. Our projects provide a small framework that is used to develop small LOB-applications that all are quite similar. Due to the fact that we deliver the framework in a set of different packages the developers can choose which of the packages they actually need and then install only those. Should a developer decide to add a missing functionality lateron he just installs the relevant packages that have the same version as those already installed. Thus there's no need to worry about compatibility.
Yes, you can "probably" make this work. I say probably because I haven't tried it, but I would approach it with something like this: https://www.nuget.org/packages/CreateNewNuGetPackageFromProjectAfterEachBuild/ with a manual nuspec defining your references would work. If you wanted to get really fancy, you could write some post-build Roslyn code to parse your project dependencies and build up the nuget dependency tree. That said, don't do this, in a non-trivial solution, its almost guaranteed to become manual and brittle pretty fast.
Ultimately, it's much preferable to just break your solution up -- create a solution per Nuget package, and pull in your dependencies using Nuget itself. Assuming you have a build/CI server, this should be fairly trivial. Just run your own Nuget repo and publish the build artifacts as they get built -- that way your dependent projects will pull the latest package you JUST built. You'll want to ensure your build process refreshes Nuget each time and you can use the standard nuget spec
command as a post-build step. As a nice bonus, it'll force everyone working on the code to really think thru the dependencies when making changes.
Currently, in VS 2017 you can have several library projects in a solution which are built into separate packages and also reference each other by <ProjectReference>
. Surprisingly, VS is smart enough to use <ProjectReference>
when building solution AND to produce correct package <dependencies>
for referenced projects in nuspec. In other words, you can conveniently work with many projects simultaneously in one solution and have them all published as a set of packages depending on each other.
来源:https://stackoverflow.com/questions/28097335/declaring-nuget-packages-that-depend-on-each-other-in-one-solution