One thing that is important to get nailed down early is the project directory structure.
Making directory structure changes after the project has started are distruptive and time consuming to make. At a minimum it will affect:
How you have set up your source control.
How your game deals with paths for reading files.
How you and your team are used to working.
How your include paths for headers and libraries are set up.
Here is how I've set up my project, which is a cross-platform space combat simulation:
projects/twilight/bin/win32
projects/twilight/code/game
projects/twilight/code/engine
projects/twilight/data/fonts
projects/twilight/data/levels
projects/twilight/data/meshes
projects/twilight/data/textures
projects/twilight/havok
projects/twilight/irrlicht
projects/twilight/irredit
projects/twilight/obj/game/win32
projects/twilight/obj/engine/win32
The project name is twilight, and everything related to the project is under this directory.
The directories under data are not meant to be final, the data directory will be fairly dynamic until content requirements are nailed down.
The code directory contains all the code to be written for the game. It consists of two sub-projects: game and engine. The engine is set up a library and there is no inclusion of any game files in the engine project. The idea is that the engine lib can be reused for future games.
I'm using Microsoft Visual C++ 2008 Express Edition, and the solution for the project is stored in projects/twilight/code.
The code and data for the game are separated out from the external libraries and tools I'm using, namely:
irrlicht
irredit
havok
By having the code and data directories separated (and only containing code and data files), it's easy to set them up for import to source control (I'm using subversion).
The object files are put into their own directory, and are separated by project and platform. This keeps them out of the way. Along the same lines the project outputs (game executable and engine lib) are put into the bin directory (into a platform specific sub dir).
Note that I've used generic names like "game" and "engine", this is used since inevitably project names change (and it will make it that much easier to re-use on a future project). The output files are also generically named, but named such that they are easily identified as being debug or release. For example my project generates these in a Debug build:
game_debug.exe
engine_debug.lib
In Release the output files are named:
game_release.exe
engine_release.lib
To make this directory structure compatible with both irredit and the game, I've specified the working directory for both projects to be projects\twilight. This means resources will use relative pathnames in the form:
data\levels\test.irr
etc.
I'd be curious to hear what others use for their projects, and views on directory/file organization in general.
Project directory structure
Interesting topic. My new project is some VR (so let's call it SomeVR) which has lots of libs, is cross-platform (using several compilers planned) and has several executables (client, server, etc).
The main-structure:
\SomeVR
Information about the project (like a description of the file-structure)
Some files which need to be accessed daily and/or fast (todo.txt, ideas.txt)
-- code
The kind of stuff I would distribute if someone else would work with me. Therefore this is also the root used in my source control system (currently mercurial).
---- doc
Architecture, License information
---- client (see project subfolders)
Contains my client.
---- server (see project subfolders)
Contains my server
---- uitool (see project subfolders)
Contains a larger tool which I use to create dialogs.
---- experiment
I always have lots of code-snippets to test stuff.
---- lib (see library subfolders)
Contains all libraries used in the project.
---- shared
Contains sources which are used by several sub-projects but are not made into a lib yet. Examples:
------ input
Wrapper for input devices.
------ irrlicht_ext
Classes I need when working with Irrlicht like StringTable, a better Windowsystem, own gui elements.
------ tinyXML
Yeah, I still use often tinyXML. Might switch to boost for that stuff soon ;-)
---- releases
This folder receives files which are actually distributed. So that's the stuff I can copy 1:1 to a website for other people to try out. Each release get's it's own subfolder.
---- tools
Scripts for shell and python. Most important are the release-scripts which go trough all the other subfolders and copy the stuff together which will get into releases.
-- div
Everyone has stuff that doesn't fit elsewhere
-- documents
Stuff like contracts.
project subfolders
\subproject
Executables (can be several like clientD for Debug, clientP for profile and client.exe for the release windows executable):
This is also my working directory and the executables are directly copied in here after compilation. Releases will have the same relative path to the media folder, so I can use this from within the IDE from outside and in the release the same way.
DLL's: Usually copied in the pre-build step from the library folders. For example in Code::Blocks such a command would look like:
cmd /c xcopy ..\..\lib\irrlicht\lib\Win32-gcc\IrrlichtD.dll ..\IrrlichtD.dll /D
-- doc
Documentation specific for this sub-project.
-- lib
This contains shared runtime libs which are addressed by an rpath on linux. Like dll's.. only that I haven't found out yet how to put dll's in here.
-- media
Contains all media files. Can have any number of subfolders like /levels, /dialogs, /texts, etc...
-- src
Project sources. Can also have any number of subfolders.
-- several IDE folders
For example one such folder is named CodeBlocks. And it contains all files which codeblocks wants to handle. Right now for example workspace files, but it also has all the .obj files. This is rather tricky - each IDE wants to do this different. Some won't even accept it if they can't have all their projectfiles in the mainfolder of the project (which disqualifies them for me automatically, so it's not such a big problem for me). Therefore sub-folders are ide-specific. But in my case for C::B they look as follows:
---- linuxDebug
---- linuxRelease
---- mingw_gccDebug
---- mingw_gccRelease
library subfolders
\mylib
This depends on each library. Usually I try to change as little as possible and work with existing structures. In most cases I add one folder level to switch easier between different library versions. Example:
-- boost
---- boost_1_36_0
Library names should contain the compile information. Like irrlichtD for Debug or irrlichtP for profile. Boost does that stuff rather nice already, for example: libboost_serialization-gcc43-mt-1_36.so.1.36.0
I guess I will change some of my names to make them look more like that.
The main-structure:
\SomeVR
Information about the project (like a description of the file-structure)
Some files which need to be accessed daily and/or fast (todo.txt, ideas.txt)
-- code
The kind of stuff I would distribute if someone else would work with me. Therefore this is also the root used in my source control system (currently mercurial).
---- doc
Architecture, License information
---- client (see project subfolders)
Contains my client.
---- server (see project subfolders)
Contains my server
---- uitool (see project subfolders)
Contains a larger tool which I use to create dialogs.
---- experiment
I always have lots of code-snippets to test stuff.
---- lib (see library subfolders)
Contains all libraries used in the project.
---- shared
Contains sources which are used by several sub-projects but are not made into a lib yet. Examples:
------ input
Wrapper for input devices.
------ irrlicht_ext
Classes I need when working with Irrlicht like StringTable, a better Windowsystem, own gui elements.
------ tinyXML
Yeah, I still use often tinyXML. Might switch to boost for that stuff soon ;-)
---- releases
This folder receives files which are actually distributed. So that's the stuff I can copy 1:1 to a website for other people to try out. Each release get's it's own subfolder.
---- tools
Scripts for shell and python. Most important are the release-scripts which go trough all the other subfolders and copy the stuff together which will get into releases.
-- div
Everyone has stuff that doesn't fit elsewhere
-- documents
Stuff like contracts.
project subfolders
\subproject
Executables (can be several like clientD for Debug, clientP for profile and client.exe for the release windows executable):
This is also my working directory and the executables are directly copied in here after compilation. Releases will have the same relative path to the media folder, so I can use this from within the IDE from outside and in the release the same way.
DLL's: Usually copied in the pre-build step from the library folders. For example in Code::Blocks such a command would look like:
cmd /c xcopy ..\..\lib\irrlicht\lib\Win32-gcc\IrrlichtD.dll ..\IrrlichtD.dll /D
-- doc
Documentation specific for this sub-project.
-- lib
This contains shared runtime libs which are addressed by an rpath on linux. Like dll's.. only that I haven't found out yet how to put dll's in here.
-- media
Contains all media files. Can have any number of subfolders like /levels, /dialogs, /texts, etc...
-- src
Project sources. Can also have any number of subfolders.
-- several IDE folders
For example one such folder is named CodeBlocks. And it contains all files which codeblocks wants to handle. Right now for example workspace files, but it also has all the .obj files. This is rather tricky - each IDE wants to do this different. Some won't even accept it if they can't have all their projectfiles in the mainfolder of the project (which disqualifies them for me automatically, so it's not such a big problem for me). Therefore sub-folders are ide-specific. But in my case for C::B they look as follows:
---- linuxDebug
---- linuxRelease
---- mingw_gccDebug
---- mingw_gccRelease
library subfolders
\mylib
This depends on each library. Usually I try to change as little as possible and work with existing structures. In most cases I add one folder level to switch easier between different library versions. Example:
-- boost
---- boost_1_36_0
Library names should contain the compile information. Like irrlichtD for Debug or irrlichtP for profile. Boost does that stuff rather nice already, for example: libboost_serialization-gcc43-mt-1_36.so.1.36.0
I guess I will change some of my names to make them look more like that.
Last edited by CuteAlien on Sun Nov 02, 2008 9:25 am, edited 1 time in total.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
tbh, ice9s approach looks a little messy
I tend to have external libraries separate from the project so you can include them in multiple projects. All the source belonging to the project goes in the project name/src/ folder.
IE:
projects/Irrlicht1.4.2/
projects/project1/ <-- make & .dev & msvc files here
projects/project1/src <-- .cpp & .h files here
projects/project2/ <-- so project 1 & 2 can use irrlicht 1.4.2
This tidies things up when upgrading libs and include files. A lot of people like to put includes in their compiler include directories, but I found using multiple compilers this becomes a hassle
of course there's the debug/, release/ and obj/ folders used in compiling and testing
I tend to have external libraries separate from the project so you can include them in multiple projects. All the source belonging to the project goes in the project name/src/ folder.
IE:
projects/Irrlicht1.4.2/
projects/project1/ <-- make & .dev & msvc files here
projects/project1/src <-- .cpp & .h files here
projects/project2/ <-- so project 1 & 2 can use irrlicht 1.4.2
This tidies things up when upgrading libs and include files. A lot of people like to put includes in their compiler include directories, but I found using multiple compilers this becomes a hassle
of course there's the debug/, release/ and obj/ folders used in compiling and testing
CutieAlien -- thanks for describing your directory structure. It seems you have a lot more things to deal with that me, and you've done a good job at organizing it all.
torleif -- I think there are pros and cons to including external libs/source like irrlicht and havok in the project.
On the pro-side, it is quite possible the project will customize (i.e., make code changes specific to the project) within irrlicht or havok. By isolating these files to the project, I can be sure any custom work won't affect other projects.
On the other hand, if there are no plans to make changes to these external files, I see your point about it being cleaner to have these separate from the project.
So, In my mind this is a project-decision based on expected usage of the libraries.
torleif -- I think there are pros and cons to including external libs/source like irrlicht and havok in the project.
On the pro-side, it is quite possible the project will customize (i.e., make code changes specific to the project) within irrlicht or havok. By isolating these files to the project, I can be sure any custom work won't affect other projects.
On the other hand, if there are no plans to make changes to these external files, I see your point about it being cleaner to have these separate from the project.
So, In my mind this is a project-decision based on expected usage of the libraries.
One other thing I wanted to mention is how the source files are organized. I put all the source code for game and engine is a single flat directory.
This may seem unorganized on the surface, but here are the benefits:
1. Organization of the files is done on the IDE side. Meaning I can use any folder structure I like for the code in the IDE (which is where I work 99% of the time). I can rework that as much as I like without having to move files around on the HD.
2. This eliminates the explosion of include paths, which is a maintenance issue, especially as build configurations increase in number. It's much easier to have a single include path for everything, rather than constantly adding/changing include paths as the HD directory structure changes.
This may seem unorganized on the surface, but here are the benefits:
1. Organization of the files is done on the IDE side. Meaning I can use any folder structure I like for the code in the IDE (which is where I work 99% of the time). I can rework that as much as I like without having to move files around on the HD.
2. This eliminates the explosion of include paths, which is a maintenance issue, especially as build configurations increase in number. It's much easier to have a single include path for everything, rather than constantly adding/changing include paths as the HD directory structure changes.