Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Organizing solutions, projects and SVN

I would like some help in setting up a project in SVN with regards to directory structure. I have read several answers regarding this on SO, but as I am new to this, most of them are difficult to understand.

I am building a single library, on which several other distinct project depends on:

I need the ability to export MyLibrary (headers and .lib only) easily for use by third parties

MyLibrary1

  • Depends on external libraries, should be able to manage different versions of these libraries!

MyLibrary2

  • Depends on External Libraries fmod, glew, ...

Project 1, 2, 4, 5, 6 ...

  • Depends on MyLibrary1, 2, or both
  • Each project could need versions for multiple platforms (osx, windows ...)

I would like to know of a good way to organize this, do keep in mind that I am rather new to this - a more pedantic answer would be helpful. For example if you write something like /src, do explain what is supposed to go into it! I would be able to guess, but I wont be sure =)

////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Edit

I cant put this into a comment, so here goes: @J.N, thanks for the extensive reply, I would like to clarify some stuff, I hope I understood what you meant properly:

root
    library foo
        /branches           // old versions of foo
        /tags               // releases of foo
        /trunk              // current version
            /build          // stuff required by makefiles
            /tools          // scripts to launch tests ect
            /data           // test data needed when running
            /output         // binaries, .exe files
            /dependencies   // libraries that foo needs
                /lib name
                    include
                    lib
            /docs           // documentation
            /releases       // generated archives
            /sample         // sample project that shows how to use foo
            /source         // *.h, *.cpp

    program bar
        /branches           // old versions of bar
        /tags               // releases of bar
        /trunk              // current version
            /build          // stuff required by makefiles
            /tools          // scripts to launch tests ect
            /data           // test data needed when running
            /output         // binaries, .exe files
            /dependencies   // libraries that bar needs
                /lib name
                    include
                    lib
            /docs           // documentation
            /releases       // generated archives
            /sample         // sample project that shows how to use bar
            /source         // *.h, *.cpp

1) Where do the *.sln files go? In /build?

2) do I need to copy foo/source into bar/dependencies/foo/include? After all, bar depends on foo

3) Where do *.dll files go? If foo has dependencies on dll files, then all programs using foo need access to the same dll files. Should this go into root/dlls?

like image 597
aCuria Avatar asked Mar 02 '12 12:03

aCuria


1 Answers

There are several levels to your questions: how to organize a single project source tree, how to maintain the different projects together, how to maintain the dependencies of those project, how to maintain different variants of each projects and how to package them.

Please keep in mind that whatever you do, your project will eventually grow large enough to make it unadapted. It's normal to change the structure several times in the lifetime of a project. You'll get the feeling that it isn't right anymore when that will happen: it's usually when the setup is bothering you more than it helps.


1 - Maintaining the different variants of each project

Don't have variants for each project, you won't solve several variants by maintaining parralel versions or branches. Have a single source tree for every project/library that can be used for all variants. Don't manage different "OSes", manage different features. That is, have variants on things like "support posix sockets" or "support UI". That means that if a new OS come along, then you just need to choose the set of features it supports rather than starting a new version.

When specific code is needed, create an interface (abstract class in C++), and implement the behaviour with respect to it. That will isolate the problematic code and will help adding new variants in the future. Use a macro to choose the proper one at compile time.


2 - Maintaining the dependencies of each project

Have a specific "dependencies" folder in which each subfolder contains everything needed for one dependency (that is includes and sub dependencies). At the beggining when the codebase is not too large, you don't care too much about ensuring automatically that all the dependencies are compatible with each other, save it for later.

Don't try to merge the dependencies from their root location higher in the svn hierarchy. Formally deliver each new version to the teams needing it, up to them to update their own part of the SVN with it.

Don't try to use several versions of the same dependency at once. That will end badly. If you really need to (but try avoiding it as much as you can), branch your project for each version.


3 - Maintain the different projects

I'd advise to maintain each projects repository independently (with SVN they still could be the same repo, but in separated folders). Branches and tags should be specific to one project, not all of them. Try to limit to a maximum the number of branches, they don't solve problems (even with git). Use branches when you have to maintain different chronoligical versions in parallel (not variants) and fight back as much as you can before you actually do it, everybody will benefit from the use of the newer code.

That will allow to impose security restrictions (not sure if feasible with vanilla SVN, but there are some freely available servers that support it).

I'd recommend sending emails notifications whenever someone commits on a project to everybody potentially interested.


4 - Project source tree organization

Each project should have the following SVN structures:

  • trunk (current version)
  • branches (older versions, still in use)
  • tags (releases, used to create branches without thinking too much when patches are required) When the project gets bigger, organize branches and tags in sub folders (for instance branches/V1.0/V1.1 and branches/V2.0/V2.1).

Have a root folder with the following subfolders: (some of this may be created by VC itself)

  • Build system (stuff required by your makefiles or others)
  • Tools (if any, like an XSLT tool or SOAP compiler, scripts to launch the tests)
  • Data (test data you need while running)
  • Output (where the build system put the binaries)
  • Temp Output (temporary files created by the compilation, optional)
  • Dependencies
  • Docs (if any ;) or generated docs)
  • Releases (the generated archives see later)
  • Sample (a small project that demonstrate how to use the project / library)
  • Source ( I don't like to split headers and .cpp, but that's my way )
    • Avoid too many levels of subfolders, it's hard to search trees, lists are easier
    • Define properly the build order of each folder (less necessary for VC but still)
    • I make my namespaces match my folders names (old Java habits, but works)
    • Clearly define the "public" part that you need to export
    • If the project is large enough to hold several binaries / dlls each should have its own folder

Don't commit any binaries you generate, only the releases. Binaries like to conflict with each other and cause pain to the other people in the team.


5 - Packaging the projects

First, make sure to include a text file with the SVN revision and the date, there's an automated way to do that with auto props.

You should have a script to generate releases (if time allows). It will check that everything is commited, generate a new version number .... Create a zip/tar.gz archive you must commit/archive, whose name contains the SVN revision, branch and the current date (the format should be normalized accross projects). The archive should have everything that is needed to run the app / use the library in a file structure. Create a tag so that you can start from it for emergency bug fixing.

like image 117
J.N. Avatar answered Sep 21 '22 00:09

J.N.