We have several solutions that reuse the projects in the [DO NOT EDIT] folder. How can I remove these projects from my solution?
I do need the most recent version of this projects always. We obviously do not check-in the binaries. Should we start to do that?
Without having to configure nuget packages, how do we reference other projects without having to explicitly load them in the same solution?
You have several options referencing assemblies that aren't in the solution:
Supply them as NuGet package.
Have them in VCS (tfs, git), e.g. in 'lib' folder and referencing by the relative path.
Put them in some server share and referencing them via UNC path, e.g.
\\SOMESERVER\Assemblies\MyAssembly.dll.
From my experience 1st method works much better than 2nd, and 2nd is better than the 3rd.
However if for some reason you don't want these assemblies in VCS and don't want to configure NuGet packages, then 3rd option should work for you.
Related
I've tried to look at many of the questions asked here about it, but none is exactly like my set-up.
Also, this issue is NOT directly related to Nuget, but it might be part of the solution.
I have a project which consists of a few solutions. All of the projects in those solutions use the same output path.
Example:
-Root
--Solution1
--Solution2
--Solution3
--OutputForAllProjectsInAllSolutions
I want to use NuGets in those solutions. The problem is if I'll use different version of the same NuGet package in each solution, then the each solution will override it's predecessor's reference dlls.
I was thinking of a solution, but I don't know if it's possible and how.
Something like:
-Root
--Solution1
--Solution2
--Solution3
--PackagesFolderForAllSolutions // can be done with repositoryPath right?
--OutputForAllProjectsInAllSolutions
---NugetPackageVersion1
---NugetPackageVersion2
---NugetPackageVersion3
Is it a possible? Is it a good solution? How to do it?
If not, any better suggestions?
Thanks in advance.
EDIT: I wish I could use 1 solution for all, but it's legacy code, and it has too much complexity.
The setup is 1 source-code repository with multiple solutions.
The real question appears to be "how can I make sure all projects use the same version of a dependency", but it's unclear to me if you proposed using a shared packages folder in order to save disk space. Using a shared folder will not solve the multiple versions problem, you'll just end up with a packages folder with multiple versions of a package, but maybe you want to save disk space, so I'll answer that as a separate question. I'm going to avoid the opinionated 'is it a good solution', but in my opinion the "better solution" you asked for is to migrate all projects to PackageReference and use the solution I give below. Also considering using a single solution, but that's unrelated to nuget package versions.
How can I make sure all my projects are using the same version of a NuGet dependency
Code in multiple source control repositories
If your code is spread across multiple source code repositories, then if your cross-project references are internal nuget packages, the projects that depend on projects from other repos via a nuget package will get external nuget dependencies transitively, so simply avoid upgrading nuget packages in your downstream projects. Upgrading will mean upgrading in your upstream project, generate a new nuget with a higher dependency version, generating a package, then updating the version of your internal package in your downstream project. It's a lot of effort, which is why I dislike having applications/systems spread across multiple source code repositories. There may still be reasons to do it which outweigh the costs, and to me that's what engineering is all about, dealing with trade-offs.
Code in single repository. Multiple solutions, NuGet packages via packages.config
If your code is in a single repository, at least one of your projects use packages.config and your application is spread across multiple solutions, then there's still going to be a reasonable amount of manual work, but the fewer packages.config projects there are, the less work there will be. You could use the method for a single solution application, and do it multiple times for each solution.
One solution, NuGet packages via packages.config
Right click the solution, select "Manage NuGet Packages for Solution", then go to the Consolodate tab.
NuGet packages via PackageReference
If you're using PackageReference, it doesn't matter if your repo has a single solution or multiple solutions. You can create a MSBuild props file with your NuGet package versions. As an example, have a look at this ASP.NET Core example. If you put these properties in a file named Directory.Build.props at the repo root, newish versions of MSBuild should (I've never tested it myself) import it automatically. Otherwise you'll need to edit all your project files to include an import to the props file. Then you edit the project files and change the version to use the MSBuild property. Again, example from the ASP.NET Core repo. Downside is that you can no longer use Visual Studio to update the package versions, but you can still use it to check for new versions and see what the newest versions are.
If your application has multiple repos, and multiple projects are using PackageReference, you can look into putting the props file in a git submodule, or something equivalent for your source control system.
In conclusion
I strongly recommend migrating from packages.config to PackageReference, and then you can use a MSBuild props file to automatically keep all projects using the same version of each dependency.
Can I reduce disk space by using a single packages folder for multiple solutions
Firstly, if all your projects used PackageReference, this wouldn't be an issue because NuGet does not copy PackageReference packages into solution folders, so there's even less disk usage than using packages.config with a shared packages folder, because you're still going to have one copy in the global packages folder and another in the solution packages folder.
But if you can't/won't migrate to PackageReference, then yes, as you asked in your question, you can use a nuget.config file at the root level to set <repositoryPath>packages</repositoryPath> to make all the solutions use the same packages folder at the root level, as long as the solution folders don't have their own nuget.config file that overrides the setting. You can change packages to anything you want, but I discourage using ..\anything because I hate it when projects write files outside of their repository root.
There is one shared solution which uses packages (obtained via nuget, for example Elmah). This solution generates DLLs.
I have several solutions which want to use those dlls. I've added them via "Add reference".
This works when I have my nuget packages installed on every solution, but when i uninstall it from the descendant - it can't find it. I understand why (it does not copy folder with packages from sharedSolution, only generated DLLs), but I wonder what is best practice in such situation?
If you prefer to manage the DLLs shared across multiple solutions manually, the steps would be:
After loading the NuGet package to one of your solutions, navigate to the package location and copy all the required DLLs (with the supporting XML files, if any) to a separate folder (e.g. Vendors\SharedPackage.Version1).
Uninstall the NuGet package.
Now using "Add reference", navigate to the location where you copied the SharedPackage in step 1 (Vendors\SharedPackage.Version1 folder) and add the required reference to all projects and solutions you want.
Note: If you go down this path, you'll have to manage all the SharedPackage updates manually: Get the updated package via NuGet, copy the package contents to a separate folder (Vendors\SharedPackage.Version2), uninstall the package, remove references to the old package from all your projects in all solutions, add references to the new version of the SharedPackage.
Alternatively, if you want to have your NuGet packages managed by the Visual Studio, this thread is the best source of information I could find on this topic. Vermis has done a great research work!
P.S. Imho, the manual solution is easier to implement but harder to maintain. The decision is up to you.
I have a smallish solution, with about under twenty projects. The solution used to also contain about six source projects written by a third party service provider, ACME. Now, finally, this other party is supplying us only with a handful of DLLs. I used to just included their source, one project per DLL, in the solution, and so I am looking for a neat way to include all these assemblies in the solution, so they can be referenced from the many projects that need them.
My immediately apparent options are:
Create an AcmeAssembly project, add all DLLs as project items set to copy to output.
Create an AcmeAssembly solution folder. Quicker and simpler than a 'binary-only' source project, but solution folders have the very, very large drawback of having no means of grouping the files without a solution file, i.e. outside of VS.
Create a NuGet package that includes all the required binaries. Then at least we also have a partly 'phycical' grouping in the packages folders. My problem here is I have never written a NuGet package, but I am not asking how to here. I am asking about three candidate solutions, and more will be welcome, and if NuGet wins, I get to learn to write a package.
I can't simply use the project's output bin\debug and bin\release folders. To me, these are strictly output folders, and nothing but other dependency assemblies should also be output there. Deleting the bin folder should have absolutely zero effect on a build, so that is certainly no place to store binaries.
The advantages of nuget over the other solutions are:
Support for versioning
Support is built in into Visual Studio and MSBuild
No 'magic folders' that all developers need to have on their machines
Create your Acme library folder (something like: C:\Source\Library\AcmeLibrary). Put all of your Acme dll's in that folder. Then create the Solution Folder in VS and add the existing items to it (don't add the folder, but the items in the C:\Source\Library\AcmeLibrary folder to the solution folder using "Add Existing Item..." menu selection).
I'm curious how others do it, or if there's an easier way...
I'm having multiple projects which are referencing the same DLL i.e. nhibernate.dll.
Those dlls are stored in version folders like NHibernate-3.2.0.
If a new version comes out and we are going to upgrade to it, we create a new version folder and need to update all referencing projects to the new dll.
Is there some easier way to do that? Like some central project (lets call it REF_PROJ) which references nhibernate and all other projects are only referencing REF_PROJ?
So the updating of the new version has only be done at one central place, the REF_PROJ.
Your solution is one way. The "better" way IMHO is to use nuget packages. Specifically the nhibernate nuget package. Then you can right click on the solution and update all the nhibernate packages when a new version comes out.
EDIT: To add to the other answer. If you wish to use a specific version of the nuget package that targets a particular version of the assembly in the package, use --version when you install them from the package manager console.
Just have a root folder, not version specific. Or if you really need version specific, then have 2 copies - one in the root folder and one in a version specific folder.
here is an example of what i mean.
nhibernate
--> nhibernate 3.2
----> nhibernate.dll
--> nhibernate.dll
Another solution is to using the GAC
register your assemblies into gac, and add reference to it from multiple projects without specifing assembly version . and update it easy with gac util.
I'm trying to figure out what the best way to handle this scenario is.
Let's say I have a library that's referenced by multiple different non-related solutions, let's call it WebServiceInterface.dll. This library has a dependency on JSON.NET.
Before NuGet
The JSON.NET binary was referenced via a SVN external in the WebServiceInterface project. Other solutions which had a dependency on WebServiceInterface referenced the project (also as an SVN external) and as a result pulled both the project, and it's dependencies.
With NuGet
I haven't figured out how to force the JSON.NET reference to be stored under the WebServiceInterface project (as opposed to the RandomSolution\packages location). I found reference # nu-get to project-level and solution-level pacakges, but I can't seem to find out how to specify this when I add a dependency via nu-get.
The goal here is that when someone checks out WebServiceInterface and adds it to a new solution that it builds (instead of having broken references to JSON.NET which point to the packages directory under whatever the last solution was that checked in).
When I went to find out if Chris B had created a NuGet issue for this, I couldn't find one. EDIT: He did, see his comment below. But I did find a semi-documented feature of NuGet that I used to solve this problem: Allow specifying the folder where packages are installed
Let me break this question into 2 issues:
getting NuGet to allow for multiple solutions to use the same packages location
getting the NuGet packages to automagically fetch from source control when you include a project that has NuGet packages
Problem 1:
By default NuGet stores packages in a packages folder in the solution's folder. To change that location, create a nuget.config file in the solution's root folder with the following contents:
<settings>
<repositoryPath>..\..\..\Utilities\Library\nuget.packages</repositoryPath>
</settings>
<repositoryPath> is relative to your solution; so obviously make it whatever you want. Make each solution have it's own relative path to the same packages folder.
As far as NuGet's flow, from that point, the paths in repositories.config are relative to the folder containing repositories.config, not the solution, so now all projects/packages are managed independent of the solution location.
This allows multiple solutions to use the same packages in source control, and if those solutions use the same projects (that use NuGet packages), those solutions/projects will all be kept in sync no matter which solution updates the package.
Problem 1 completely solved.
Problem 2:
Let me address this from 2 perspectives. This applies to Visual Studio and TFS -- I'll leave SVN for someone else to address.
First: if you have no source code on your drive and do a get of a solution (not a project), I prefer to make it so that you get everything that solution needs to build. There shouldn't be any missing references to go manually grab. That much we can do by adding the package files as solution items. Yes, in each solution. A bit of work, yes, but when it's done the package files will fetch/update from source control automagically.
Second: In a new solution, when you include an existing source control project that has NuGet packages, you have to manually fetch the packages from source control and add them as solution items. At least anyone else getting your solution in the future will automagically get everything they need to successfully build. At least with VS/TFS, this is just the way it is, AFAIK. If projB depends on projA, and you add projB to a new solution, VS/TFS won't automatically grab projA from TFS. You have to do that manually. So then the same goes for dll references (like NuGet packages).
Summary of my solution:
Only one copy of packages in source control for all solutions
Any solution can update packages and all the other solutions will be kept in sync*
* Once one solution updates packages to new paths or file names, they will appear as missing references to the other solutions and you'll have to manually clean that up. But at least you know right where the packages are in source control "(as opposed to the RandomSolution\packages location)."
The packages are always stored at the solution level, so if you install a package into multiple projects, they came from the same place. I don't believe you can configure it so that each project has its own packages folder.
I'm not sure there's a nice way to do what you're trying. You could maybe have a build step on the project that fetches the package, but I don't know how well that will suit you.
I'd recommend posting in the NuGet Issue Tracker to get a discussion going. The people working on it seem pretty active, so it might be something they can add support for in a future version :-)