I develop a lot of different applications. They range from large inventory tracking websites, to Windows services, to user interfaces encapsulating scripts written by someone else. I get asked to make many different things. It can sometimes be difficult to keep from reinventing the wheel in different projects. So it's very useful to maintain a common library to reference from the different projects. Regardless of what you keep in the library, utilities, base classes, or the dreaded "helper methods", it does become challenging to work with.
The common library source code is kept separate from the project I'm actively working on. Because of this, I keep the compiled binaries from the common library checked into the source control of the active project. I do this to assure that the active project will always build because it is only dependent on the common library binaries, not the common library project.
As I work in the active project, I often want to move code into the common library. It's easy to make a project reference to the common library project, but I don't want to commit the files into source control this way. I want to commit with a normal reference to the binary. It would be a pain to keep switching the reference back and forth every time I make a commit.
What I have been using for this is a second solution file and conditional references in the active project files.
The second solution file is a duplicate of the primary solution file, but it also includes a project link for the external common library project and is named with "_Externals" appended to the name. For example, "Project1_Externals.sln".
The project files of the active project, contain a "Choose" condition based on the name of the solution file. So if I open the "_Externals" solution file, then I get the project reference to the external common library. And if I open the primary solution file, then I get a normal reference to the common library binary.
My projects are always setup with a script I can double click to build the project. The build script is configured to use the primary solution file and will ignore the "_Externals" solution file.
<When Condition=" '$(SolutionName)' == 'Project1_Externals' ">
<!--Reference to external project.-->
<!--Reference to the local binary in source control.-->
The workflow involved goes something like this:
- The majority of the time, I open the "_Externals" solution as I work.
- If I've made any changes to the external common library code when I'm ready to commit, then I rebuild the common library and include the newly compiled binaries with the commit.
- The common library project is part of a solution with other projects which live in their own source control repository. This is also configured with a build script I can double click to build the common library solution. The build script includes things like versioning, testing, and moving files around to construct the final output in a specified build folder.
- To streamline the process of updating the binaries for the commit, I create a quick and dirty script. This script will call the build script of the common library solution, then take the output binaries of the common library and copy them over to a "lib" folder which is part of the active project and will be included in the commit.