The project that I'm currently working on is being developed by multiple teams where each team is responsible for different part of the project. They all have set up their own C# projects and solutions with configuration settings specific to their own needs. However, now we need to create another, global solution, which will combine and build all projects into the same output directory.
The problem that I have encountered though, is that I have found only one way to make all projects build into the same output directory - I need to modify configurations for all of them. That is what we would like to avoid. We would prefer that all these projects had no knowledge about this "global" solution. Each team must retain possibility to work just with their own sub-solution.
One possible workaround is to create a special configuration for all projects just for this "global" solution, but that could create extra problems since now you have to constantly sync this configuration settings with the regular one, used by that specific team. Last thing we want to do is to spend hours trying to figure out why something doesn't work when building under global solution just because of some check box that developers have checked in their configuration, but forgot to do so in the global configuration.
So, to simplify, we need some sort of output directory setting or post build event that would only be present when building from that global, all-inclusive solution. Is there any way to achieve this without changing something in projects configurations?
Update 1
Some extra details I guess I need to mention:
We need this global solution to be as close as possible to what the end user gets when he installs our application, since we intend to use it for debugging of the entire application when we need to figure out which part of the application isn't working before sending this bug to the team working on that part.
This means that when building under global solution, the output directory hierarchy should be the same as it would be in Program Files after installation, so that if, for example, we have Program Files/MyApplication/Addins folder which contains all the addins developed by different teams, we need the global solution to copy the binaries from addins projects and place them in the output directory accordingly.
The thing is, the team developing an addin doesn't necessary know that it is an addin and that it should be placed in that folder, so they cannot change their relative output directory to be build/bin/Debug/Addins.
The key here is that team is responsible for a deliverable. That deliverable is a collection of binaries. So the "global" solution ... or "product that uses the deliverables from teams" is interested in ensuring that all of the 'current deliverables' work together. That is, that you have a deliverable from the collaborative effort.
So this begs a few questions. Do the team deliver what they consider to be a 'release'. This may be automatic in the build system. If it builds and all tests pass then publish it.
What you are looking for is a team publishing or promoting a release. The source code is how you got there, the binaries are the result. Each team controls what binaries it considers to be a release (this may be automated by the build system).
Not exactly what you asked, but I hope it is the answer that leads to the right questions to give good results.
One very simple way would be to create the solution. Include all the projects and add a project (or more) to handle the global solution build tasks. The projects in the global solution should then have a reference to the projects they need and then let Visual Studio handle how to get the binaries from each project. They will (under normal circumstances) be copied to the output folder of the build project. So the project added specifically for the global build tasks would have a copy of all the referenced projects
Another way would be to create a global MSBuild script that references the rest of the build scripts. Each project is on it's own a MSBuild script
EDIT
From the comments it would seem that there are two categories of projects. One that needs building and one that does not.
For those that need building reference them as projects in the aggregating project for those that do not require building add them either as references or add the dll as resources.
Using the later change the property of the Build action to None and copy to output directory to Copy if newer
In both cases you now have all dll's in the output directory you can then have a post build action on the aggregating project moving the dlls that should be in a specific folder (ie not in the output folder)
Have a look at the practice of Continuous Integration and the usage of a Build Server with scripted builds. This is an indispensable instrument when developing different parts of an application as a team, and your problems are a great illustration of the reason why.
You've not mentioned if you use a Version Control system. I've found in practise that each developer maintains his/hers/their teams configuration and builds locally on there machine, since you don't check *.suo or *.user files most of the personal configuration only affects the individual team member.
On a completely seperate machine check-out the same code from all repositories and compile the project on the build machine (this can be completely automated). This maintains your build servers independance.
Don't worry about it being a "Solution". You can easily build multiple solutions one after the other.
Since the output path is relative (and probably "bin\Debug") it'll get built wherever you check it out to. If you want all the binaries in the same output folder you could tweak the output path on every configuration to match. Something like "....\bin\Debug" (obviously this affects where the projects get built to on the local machines but it might not matter). That way multiple projects would get built the same target output.
You could also include a seperate setup build on the build server which isn't on each developers local machine to package up the final product.
Related
I need to build three completely different flavors or targets for my C#/XAML UWP app. Each of them will get placed in the Windows Store using a different name and will have different branding on it. Essentially, I produce three apps that have very similar features but need to be three different apps for business reasons. There is almost zero difference in the source code for these variations.
In Visual Studio, I created three folders and each contains the icons, manifest, certificate files, etc., for the target apps. I use a pre-build event to detect the configuration that I selected for the build and copy the appropriate files to the root of the project. Note that instead of "release" and "debug" builds, I have "release1", "release2", etc. and my configuration folders use matching names.
This all worked great with Visual Studio pre-2019! When I first set things up this way, it worked and was the easiest way I could find.
Visual Studio 2019 validates the element in the project file and my build process no longer works. If I make this empty, something during the build process sets it. I think it gets set when I create app packages for the store and is otherwise untouched.
What is the better way to build multiple targets or flavors of the app? Alternatively, how can I avoid this problem (and it's a problem since that value doesn't actually help me anywhere!)
So far, I have the way I do it now and I've also considered creating separate projects for each flavor with each project using all of the code from a shared project. In fact, I have a shared project that contains code that was once shared with the Windows Phone app that was part of the same solution. I just don't know if that multiple-project solution will work or not and it's hard to justify to the boss the day or two it might take to change the project structure.
I am using Visual Studio 2008
I have two applications (AppA and AppB) that I what to be installed using one msi-installer.
Both applications have reference AppC.
This is what I did:
I created Setup Project
I created two subfolders inside of Application Folder (AppA and AppB)
I added Project Output for AppA into related subfolder
I added Project Output for AppB into related subfolder
Problem: AppC did not appear in subfolder for AppB. It looks like dependency can only appear once.
Could please tell me how to resolve this?
You should be adding "Primary Output from AppC" specifically to each of the application folders. This version of VS Setup does not appear to detect that the same dependency needs to be included in two application folders.
There are a lot of recorded problems with the VS Setup and Deployment project, especially in regards to dependency detection. Also consider that MS has stopped shipping this project type, and has chosen the ISLE as its replacement (I would recommend using WIX instead - its free and is a more modern toolset when compared to Flexera's offerings).
A merge module is overkill for a single assembly. If you had a package of assemblies that need things like COM exposure or other group behavior things that you dont want to repeat (and possibly get wrong), then a merge module is more appropriate.
I'm about to start developing a desktop application (WPF) based on a "plugin" architecture, and was going to use MEF (and its DirectoryCatalog) to discover and load plugin assemblies. We're going to be developing many plugins, so it seems sensible to keep them in separate VS solutions rather than bloat the "core" application solution, but having only ever worked on single, standalone solutions, I suspect this is going to make debugging a bit tricky. I'm using VS2013 if that makes a difference.
I'm assuming that I'll still be able to step into a plugin in scenarios where the "core" application calls a method in that plugin? And I'm guessing that once in there, I'll be able to set breakpoints in those source code files that have been "visited"? But what if I want to add a breakpoint to a different source code file - one that hasn't been visited while stepping-through? How can I open that file? In a single solution I could just open it via Solution Explorer, but not (I'm guessing) when it's in a separate assembly.
I'm trying to pre-empt any problems I might have with this multi-solution approach, and wondered if VS had any clever features to simplify some of this stuff. Having separate solutions also means first compiling the plugin solution(s) that I want to test, then compiling and running the "core" application solution. While it's only a couple of extra mouse clicks, are there (again) any VS features that could help here?
This is a common scenario and not tricky at all.
In the project properties of your plug-ins, go to Debug -> Start Action and set Start external program to the executable of your core application.
This way, you only have to compile your core application once (probably using a build script that just builds everything), and debugging a plug-in will start the core application with the debugger attached and you can debug the plug-in (as soon as your core apllication loads the plug-in assembly).
Also keep in mind that you can dettach the debugger from the running application, switch to another instance of Visual Studio with another solution opened, and again attach to your running application. This comes in handy if you e.g. debug your plug-in and want to set or use existing break points in your core application.
As long as Visual Studio is able to find the debugging symbols (the *.pdb files), stepping through the code of e.g. your core application while debugging your plug-in is also no problem.
I see two ways to do this.
The more comfortable option:
1. You can add the external solution to the core solution.
Walkthrough: Adding an existing Visual Studio solution to another solution
By doing this you can organize your solution to reference the code and still keep each plugin solution separate at the same time.
You just reference those plugin solutions from your core solution that you currently want to work on. Also, using this approach you can organize the other solutions just like you would with normal projects and move thembetween virtual solutios folders to your liking until you have the most adequate folder structure.
Quote from the article:
The nice thing about this approach is that not only are all the
projects now in one solution but at any time, you can open the
separate solutions without impacting the "master" solution and vice
versa.
The files in the references solution can be opened and edited just like any other file from your "normal" projects, and of course, you can set breakpoint like in any other code file, too.
This way you can both edityour code and step through it, which I personally find much more convenient than switching and attaching to multiple processes.
2. Add the PDB files.
Put the DLLs with their corresponding PDBs of those plugins you want to debug into a folder and configure your core application to use that folder for the DirectoryCatalog. This enables you to step into the plugin code, but you will not be able to edit them.
#Andrew
Regarding debugging, it shouldn't be an issue as long as you drop the .pdb files with assembly in directory which you are using as DirectoryCatalog.
Regarding building plugin solution before Core- as you have 1 build file for each solution, you should check if you can write msbuild commands in a .bat file to get it executed one after other.
Besides all the above suggestions, another way to debug is to attach your addin solution to the running core process. Attach to Running Processes with the Visual Studio Debugger
I've got a bunch of .dll assemblies, such as HtmlAgilityPack and MoreLinq. Where am I supposed to put these files? I usually toss them somewhere in my Projects folder, but then I'm always digging around for them. Is there a standard place to put them?
There's no standard place to put them, but make sure you:
Put them in one place
Include them in source control.
I put all my required dll's in a top level directory in my solution called "Dependencies", parallel to the project folders. I have them in source control such that when new developers check out the solution, it all compiles and works right off. It's the only way to go.
I include only the .dll files absolutely needed. This keeps it light, which is good, but then when I find some other part of MVC Contrib or whatever that I need, I have to go find the unzipped directory, which might not even be on my computer! Others put entire library directories (readme.txt and all) as part of their source control linked to the solution. This ensures you and future developers will have everything they need, but adds a little dead weight. Either is a good strategy.
Having a "Lib" folder at the same level as source projects is a common way.
To be honest, it's not the dependencies my projects have that I find hard to manage, it's the dependencies the dependencies have. I'd just like to mention NHibernate, Castle Windsor and the various Castle Windsor Facilities in particular. Getting all of those to play together on my last project cost me a lot of time.
For open source projects, I also like to have the source code handy because sometimes its useful to debug into the source code. (And sometimes because the documentation is so poor, you have to read the source code to find out how it works). I've seen VS projects arranged so that the project references the DLL yet at the same time, VS knows where to find the source code, as I write I can't quite remember how to do that.
So, a Lib folder for DLLs works for me; I often call it "Shared Dependencies".
As for open-source source code, I don't have a standard way to version that because each project is structured differently and has a different build process. I don't like to tinker with the open-source project structure or build method because then, I take responsibility for it. If for some reason, it won't build, or builds incorrectly, or produces a faulty DLL, the cause would be exceedingly difficult to track down, and I'd have to get deep into troubleshooting all of that which I dont care about at all.
In a folder UNDER your solution directory, e.g. "external" or "library". That way your continuous integration system (or other team members) can do a pull of one root from your source control system and have everything they need.
In SVN, use svn:externals to pull that directory from a different root so you can easily share library DLLS (and library projects) between solutions.
In the office we have a share on the network for referenced asseblies. These could be 3rd party or assemblies of our own that could be shared between projects.
I also, don't like the idea of putting the dll files in source control. If all the developers have access to the share all will work fine.
The visual studio directory in My Documents seems like a logical place to put them. I don't know if it's the best or anything wrong with it but at least all the libraries are found in one place.
%USERPROFILE%\My Documents\Visual Studio XXXX\Libraries
At my company we place all our shared DLL assemblies onto a network drive in a folder called Assemblies. From there, we use SyncToy to mirror changes between that folder and a folder on our local development machines (in my case C:\Assemblies with subfolders for different versions or useful third party assemblies). Using the "Reference Paths" feature of Visual Studio projects makes it very easy to select different assembly versions based only on locations.
For projects at home, I would definitely go with the idea mentioned by Jeff M of placing them in the Visual Studio folder under My Documents.
I don't have a hard and fast rule on the location. However, I would encourage consistency!
For example, I needed to to this for a small tool I'm writing for a client at the moment, so I checked their other code bases in Bitbucket which seemed to use a dependencies folder in the solution folder (alongside the other projects), so I copied that.
A lot of my projects contain the Castle/NHibernate/Rhino-Tools stack. What's confusing about this is that Castle depends on some NHibernate libraries, NHibernate depends on some Castle libraries, and Rhino-Tools depends on both.
I've built all three projects on my machine, but I feel that copying the NHibernate/Castle libraries is a bit redundant since I built Rhino-Tools using the resulting libraries from my NHibernate and Castle builds.
Right now, I include all projects in seperate folders in my /thirdparty/libs folder in my project tree. Should I simply just have /thirdparty/libs/rhino-tools in my project and use the Castle/NHibernate libs from there? That would seem to make logical sense in not duplicating files, but I also like having each project in it's own distinct folder.
What are your views on this?
This is one of the problems that we're trying to tackle in the Refix open source project on CodePlex.
The idea is that Refix will parse all the projects in your solution, and before your project compiles, copy the necessary binaries from a single local repository on your machine into a folder within the solution tree and point the projects at them. This way, there's no need to commit the binaries. Your local Refix repository will pull binaries from a remote one (we're setting one up at repo.refixcentral.com), and you can set up an intermediate one for your team/department/company that can hold any additional software not held centrally.
It will also try to resolve conflicting version numbers - Visual Studio can be too forgiving of mismatched component version numbers, leading to solutions that compile but fall over at run time when they fail to load a dependency because two different versions would be needed.
So to answer the question "how do you package external libraries in your .Net projects", our vision is that you don't - you just include a Refix step in your build script, and let it worry about it for you.
I use a folder for each, which seems to be the convention.
Does it really make a difference if you're copying them?
What if you want to switch one out? Let's say you go with a new O/R mapper. It will be much easier to just delete the NHibernate folder than to selectively delete DLLs in your Rhino-Tools folder.
Take this to it's logical conclusion and you won't have any folder organization in your lib folder since everything uses log4net :)
Add additional probing paths to your app.config files to locate the dependency dlls. This way your can get away with having just one copy of everything you want. Though there are some quirks to using this feature (you must create the folder structure in a certain way). Look here for more details on the tag.
I will definetly recommend having a thirdparty or vendor folder in each of your project trees. If you find it annoying to have 32 copies of the rhino-tools package, you can have a single copy of it in your code repository, and do external references to it in your project tree.
Lets say you are using SVN, you can make a repository called "thirdparty libs" and in this have versioned copies of the libs. You then make an external property on your "thirdparty"-folder in your project tree which then in turn automaticly will do a check out of your centralized thirdparty libs. This way you for instance only have to update in one place if a security or a bugfix comes out, but each project is still in command of choosing which thirdparty libs, and which versions to use.
About the deps internally in thirdparty libs, i wouldn't mind those. The first time you compile your project, and some of the libs arent copied to your bin-folder because of implicit dependencies you can add an external attribute into your bin-folder, which will then automaticly check out the missing libs. That way you still only have to update your thirdparty libs in one place.