views:

299

answers:

6

Hypothetically, I have a project "MyFramework" that has a bunch of code used across a lot (12?) of solutions. Each of the solutions including "MyFramework" are in there own source control (SVN).

MyFramework is strictly an internal product and doesn't have a formal release schedule.

Each of the solutions are internal projects (no client work) and do have formal release schedules.

I'd prefer not having to build and copy the DLLs to all 12 projects.

New developers need to be able to sit down. svn-checkout and get to work.

What is the best way to share MyFramework across all these solutions.

+3  A: 

That sounds like a disaster... how do you cope with developers undoing/breaking the work of others...

If I were you, I'd put MyFrameWork in a completely seperate solution. When a developer wants to develop one of the 12 projects, he opens that project solution in one IDE & opens MyFrameWork in a seperate IDE.

If you strong name your MyFramework Assemby & GAC it, and reference it in your other projects, then the "Copying DLLs" won't be an issue.

You just Build MyFrameWork (and a PostBuild event can run GacUtil to put it in the asssembly cache) and then Build your other Project.

Eoin Campbell
that is certainly a consideration, but we do have CI on all projects so at least we'd find it soon.As far as GAC, I'd like to avoid the GAC if at all possible.
Kyle West
A: 

I agree with another poster - that sounds like trouble. But if you can't want to do it the "right way" I can think of two other ways to do it. We used something similar to number 1 below. (for native C++ app)

  1. a script or batch file or other process that is run that does a get and a build of the dependency. (just once) This is built/executed only if there are no changes in the repo. You will need to know what tag/branch/version to get. You can use a bat file as a prebuild step in your project files.

  2. Keep the binaries in the repo (not a good idea). Even in this case the dependent projects have to do a get and have to know about what version to get.

Eventually what we tried to do for our project(s) was mimic how we use and refer to 3rd party libraries.

What you can do is create a release package for the dependency that sets up a path env variable to itself. I would allow multiple versions of it to exist on the machine and then the dependent projects link/reference specific versions.

Something like

$(PROJ_A_ROOT) = c:\mystuff\libraryA

$(PROJ_A_VER_X) = %PROJ_A_ROOT%\VER_X

and then reference the version you want in the dependent solutions either by specific name, or using the version env var.

Not pretty, but it works.

Tim
+5  A: 

Since you mention SVN, you could use externals to "import" the framework project into the working copy of each solution that uses it. This would lead to a layout like this:

C:\Projects
  MyFramework
    MyFramework.csproj
    <MyFramework files>

  SolutionA
    SolutionA.sln
    ProjectA1
      <ProjectA1 files>
    MyFramework   <-- this is a svn:externals definition to "import" MyFramework
      MyFramework.csproj
      <MyFramework files>

With this solution, you have the source code of MyFramework available in each solution that uses it. The advantage is, that you can change the source code of MyFramework from within each of these solutions (without having to switch to a different project).

BUT: at the same time this is also a huge disadvantage, since it makes it very easy to break MyFramwork for some solutions when modifiying it for another.

For this reason, I have recently dropped that approach and am now treating our framework projects as a completely separate solution/product (with their own release-schedule). All other solutions then include a specific version of the binaries of the framework projects.

This ensures that a change made to the framework libraries does not break any solution that is reusing a library. For each solution, I can now decide when I want to update to a newer version of the framework libraries.

M4N
I like this approach, I'll have to read more about externals. I'm assuming you can change everything and commit to the right repo when you're done.The framework is very young (we recently realized we were writing the same code all over the place) so being able to make quick changes is high on the priority list. Making sure those changes don't also break everything else is also important.
Kyle West
+1  A: 

The "best way" will depend on your environment. I worked in a TFS-based, continuous integration environment, where the nightly build deployed the binaries to a share. All the dependent projects referred to the share. When this got slow, I built some tools to permit developers to have a local copy of the shared binaries, without changing the project files.

John Saunders
+2  A: 

Does work in any of the 12 solutions regularly require changes to the "framework" code?

If so your framework is probably new and just being created, so I'd just include the framework project in all of the solutions. After all, if work dictates that you have to change the framework code, it should be easy to do so.

Since changes in the framework made from one solution will affect all the other solutions, breaks will happen, and you will have to deal with them.

Once you rarely have to change the framework as you work in the solutions (this should be your goal) then I'd include a reference to a framework dll instead, and update the dll in each solution only as needed.

Console
A: 

svn:externals will take care of this nicely if you follow a few rules.

First, it's safer if you use relative URIs (starting with a ^ character) for svn:externals definitions and put the projects in the same repository if possible. This way the definitions will remain valid even if the subversion server is moved to a new URL.

Second, make sure you follow the following hint from the SVN book. Use PEG-REVs in your svn:externals definitions to avoid random breakage and unstable tags:

You should seriously consider using explicit revision numbers in all of your externals definitions. Doing so means that you get to decide when to pull down a different snapshot of external information, and exactly which snapshot to pull. Besides avoiding the surprise of getting changes to third-party repositories that you might not have any control over, using explicit revision numbers also means that as you backdate your working copy to a previous revision, your externals definitions will also revert to the way they looked in that previous revision ...

Wim Coenen