Check in all your binary dependencies into Source Control

In the vein of "getting started," the question came up today about how to access shared binary tools like NUnit or NAnt.  I'd say that the best practice is to have all the binary dependencies checked into your source control repository and use those copies of the tools (operating systems & database servers obviously don't apply).  Don't depend on a GAC-ed copy of NUnit or NAnt.

WHY? 

One of the tenets of a Continuous Integration strategy is a single, authoritative source repository for the application, including binary dependencies.  There are two end goals:

  1. Know exactly which versions of what (NUnit, NAnt, NHibernate, NEtc.) your code depends on
  2. Be able to walk up to a clean machine, checkout the code tree, run the automated build, and voila — you're ready to go.  Depending on a GAC-ed copy of NUnit, for example, defeats this goal. 

About Jeremy Miller

Jeremy is the Chief Software Architect at Dovetail Software, the coolest ISV in Austin. Jeremy began his IT career writing "Shadow IT" applications to automate his engineering documentation, then wandered into software development because it looked like more fun. Jeremy is the author of the open source StructureMap tool for Dependency Injection with .Net, StoryTeller for supercharged acceptance testing in .Net, and one of the principal developers behind FubuMVC. Jeremy's thoughts on all things software can be found at The Shade Tree Developer at http://codebetter.com/jeremymiller.
This entry was posted in Continuous Integration, Starting a new Project. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Adam Tybor

    We keep our dependencies in vendor branches and use the svn:external property to include them in source control. This allows for auto updates of dependencies, if the build breaks we just have to point the svn:external to previous version. It works nice and it helps us resolve issues with dependency versions much quicker. The only downside is when we tag we need to ensure the libs point to the correct revision of the dependency.

    /projects/projectA
    /trunk
    /lib
    nhibernate=https://repo/vendor-bin/nhibernate/latest
    rhino-commons=https://repo/vendor-bin/rhino-commons/latest
    /src
    /vendor-bin/
    /nhibernate
    /latest
    /1.2.0-CR1
    /1.2.0-GA
    /rhino-commons
    /latest

  • AdamVandenberg

    jimbolla (or anyone), where do you put your build outputs?
    The Visual Studio default of adding obj + bin folders to every project seems less than optimal.

    Also, what’s a good list of svn:ignore patterns for Visual Studio work?
    I’m used to letting Visual Studio handle its own ignores (via the source control provider), but in this case I’m not using one.

  • Andy

    You should have a look at the Maven projects for Java. Their dependency management scheme is quite nice and obviates the need to place binaries in an SCM. What I never liked about storing dlls, etc in an SCM is when you have multiple projects that use the same binaries– you end up having copies of the same binary throughout an SCM.

  • http://devlicio.us/blogs/jim_bolla/ jimbolla

    We use a similar structure:

    /Engagement Name 1/
    Main Development/
    Solution Name.build
    Solution Name.fxcop
    Solution Name.sln
    Application/
    Project.Domain/
    Project.Persistence/
    Project.Presentation/
    Project.WebApplication/
    Databases/
    Schema Scripts/
    Queries/
    Dependencies/
    Atlas/
    NHibernate/
    Project Stuff/
    Tests/
    Project.Domain.Tests/
    Project.Persistence.Tests/
    Project.Presentation.Tests/
    Tools/
    FxCop/
    NAnt/
    NMock2/
    NUnit/
    Release Candidate Stabilization/
    (branch of main)
    Production Bug Fixes/
    (branch of main)

    /Engagement Name 2/
    ….

    We’ve broken the bonds of the cryptic abbreviated folder names. :) All the tools are there for CruiseControl.NET to build/test/analyze each commit. Note the “project stuff” folder; that’s where we keep requirements, estimates, developer notes, client messages… whatever is important.

    PS: I hope the comments engine doesn’t chew up my indenting because this would look like crap.

  • Carlton

    What Tim said

  • Tim Dallmann

    I fully agree. When using VS.Net 2005 with Team System source control, I include a /lib folder in my project, and let the /bin stay out of source control. Project references are made to the /lib folder, and so the automated build also finds them easily.
    I go one step further, and include all internally developed dependancies in /lib as well. This way, each project includes the specific version of the dependancy that it was compiled with. When the dependant dll is updated, the maintenance developers of the projects that use that dll can decide when to implement the new version.

  • http://codebetter.com/blogs/jeremy.miller jmiller

    I do it like that, just with /bin and /source instead of /lib and /src. TreeSurgeon basically does the same thing.

  • http://www.hdri.net Chad Myers

    Oops, ‘Jeremy’, rather. Sorry, too many ‘e”s in there.

  • http://www.hdri.net Chad Myers

    We usually have our SVN structured like this:

    /project
    /tags
    /…
    /trunk
    /lib
    /src

    So that the lib (binary dependencies) get versioned with the src so it’s recompile-able throughout history.

    How do you (Jeremey and community) structure it?