views:

536

answers:

2

I'm using subversion and nant (and visual studio IDE)

I've been following the suggested project structure at http://blog.jpboodhoo.com/NAntStarterSeries.aspx which advocates self contained subversion directories where a developer can do a checkout and immediately build a project in a single step.

My repo structure is like:

/Repo
  /MainProject
    /trunk
      /doc   <-- documentation
      /lib   <-- binary-only DLLs
      /src   <-- source code for MainProject
      /tools <-- holds tools like nant, nunit, etc
...
  /ClassLibrary1
    /trunk
      /doc
      /lib
      /src
      /tools
...
  /ClassLibrary2
    /trunk
      /doc
      /lib
      /src
      /tools

What's not clear is how to structure a project that has class libraries which in turn reference third party library dll's themselves.

Currently, I have a main project with a working directory like

Example:

/MainProject
  /build
  /lib
  /src
    /MainProject
    /ClassLibrary1 <-- svn external to svn://server/repo/ClassLibrary1/trunk/src
    /ClassLibrary2 <-- svn external to svn://server/repo/ClassLibrary2/trunk/src
  /tools
  ...

When building MainProject, I compile the class libraries and output the dll's to the build folder. However, the class libraries themselves have 3rd party binary-only DLL's that they reference.

My questions is in order to build the MainProject I have to somehow get the 3rd party DLL's from the class libraries into the build output. How do I do that?

Thoughts: 1. Should I store copies of these 3rd party dlls in the MainProject's lib folder? 2. Or should my svn:external reference be to the trunk of the class library project rather than the src so that I can access the class library's lib folder? 3. Should I use the subversion 1.6 feature of svn:externals to individual files?

A: 
  1. Should I store copies of these 3rd party dlls in the MainProject's lib folder? I prefer to store any external libraries in a binaries directory under trunk but next to source...or call it references, dependencies, etc. This then allows any developer to get latest and all that is needed will come down. It doesn't need to be part of the project per se. It just needs to be accessible when the build is performed.

  2. Or should my svn:external reference be to the trunk of the class library project rather than the src so that I can access the class library's lib folder? I don't prefer this approach as it makes the process of getting a new developer up and running more convoluted. I think an assembly can go into its own repository when it has a level of importance on to itself. But I would never reference its output. It should have a build process wrapped around it that promotes a mechanism to "deploy" the output to the above references or dependencies directory. However automating the deployment like that might be fraught with issues. It would be better if the assembly had its own process around it. And when a new version of the assembly were released it would be manually embraced by a developer on the project that needed it. They could then test it, accept it, and place it into their build process. Obviously if that assembly changes on a daily basis some automation may be required.

  3. Should I use the subversion 1.6 feature of svn:externals to individual files? No. I prefer to keep a project/solution as a self contained entity. Having tenticals spread out all of the place makes dependencies more painful. Keep silos as hard as possible...bring new things in as manual as possible...or as manual as the frequency that things change will allow.

Andrew Siemer
I guess the crux of the issue is the class library project has a reference to a 3rd party DLL. This DLL is stored in the class library's lib folder (which is the folder designated for holding 3rd party binary-only DLL's) under ClassLibrary1/trunk/lib.However, the MainProject needs to somehow reference that 3rd party DLL for it's build. How do I do that?
User
So my question is this. You say that the class library is dependent upon this third party widget and it stores it in a lib folder for that project. And the problem is that your project also has a dependency on this third party widget...why not store it in a local lib folder as well?
Andrew Siemer
Do you mean a local lib folder for the Main Project or local lib folder for the Class Library project? If you mean the latter, then I need to have svn:externals to the trunk of the class library (which is my question #2 above)It's not that the main project has a direct dependency on the widget, it's that the project has a dependency on the class library. The class library in turn has its own dependencies (i.e., the class library won't fuction without access to the 3rd party DLL)
User
A: 

Personally I bring in the trunk of the referenced libraries. (Actually, I bring in the root of a tag, but that's beside the point).

If you keep a separate copy of the required dll's, then you're not really allowing the referenced library to determine what it needs for itself because all that logic is duplicated in the project. The same thing happens if you use multiple externals references or file externals to bring in the code and the dll's.

My principle here is that - the library knows what it needs, a single external reference to the library can get that library and everything it needs.

That way if you change the library's references, you can be confident that any and all projects will just pick that up. (if the IDE doesn't support this, that's the IDE's problem, not subverion's). You can also be confident as a project that if you change the version of the library you're pointing to, you'll automatically get the right references as well, and don't need to go debugging build failures to work out what's gone wrong.

Jim T
"If you keep a separate copy of the required dll's, then you're not really allowing the referenced library to determine what it needs for itself"That makes sense. I guess my resistance to that is checking out the library's "extra" folders. Especially since I keep the tools in the Library. If the Main Project references 10 class libraries, then I'll have 10 copies of nant, the libraries build scripts, etc. But maybe this is an instance of worrying about disk space when there's no need to?
User
The more I think about it, bringing in the trunk of library as an svn:external seems to be the clearest solution. I just wanted feedback of how others do it.
User
I've put my svn:externals property to grab the class libraries on the MainProject's src folder. This made total sense when I was grabbing just the trunk/src directory of the Class Libraries. However, if I switch to grabbing the trunk of the class library I'm wondering if it still makes sense to pull this into the src directory. Which directory do you put the externals property on?
User
It's not really important where, just so long as it's consistent :)I'd suggest the highest level you consistently checkout a branch at, so if you checkout the trunk all the time, put them on trunk. If you checkout src, put them on src.I actually create a folder within src called externals and put it on there. It works ok, and since I have a sibling folder called build, I can put different externals (ie, nant) in there.But whatever you do, try not to put externals at different levels, if you've got to scrub around to update references, it's a real pain. Painful things don't get done.
Jim T
I have a project where the MainProject uses several ClassLibraries and both the MainProject and the ClassLibraries use a CommonClassLibrary. So there is a kind of nested structure. In this, case do you put svn:externals on the ClassLibraries to bring in the CommonClassLibrary? If the MainProject uses 5 class libraries, this means the CommonClassLibrary would be repeated 5 times as subdirectories. How would you handle this situation?
User
Nesting can definitely become a pain, but I wouldn't get too hung up on it unless it starts to cause a problem. If it does cause a problem it'd be time to start arranging so that the problematic libraries don't get nested any more - instead pull in a subset of trunk and ensure that the project gets the common library in a separate external reference. Another possibility is to start pulling in pre-compiled binaries instead (probably from a separate repository, fileshare, etc), which is something I've considered in the past.
Jim T