Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!


1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


C++ files organisation


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
12 replies to this topic

#1 ZwodahS   Members   -  Reputation: 483

Like
0Likes
Like

Posted 23 July 2014 - 03:58 AM

I have been coding C++ for more than a year now and I just realized that the way I package my project is very different from how all the C++ open source projects package their projects.
Most of the C++ projects package in such a way that it looks like this

project
 |_ include
 |_ src

while I usually store them in deep folder structures.
project
|_folder A
 |_ sub folder A
 |_ sub folder B
|_ folder B

When I learn a language, I want to embrace it fully and not just use it like another language. But before I migrate some of my projects, I thought I asked, what are the advantages/disadvantages to doing either way ? I know my way probably came from back when I just started programming and Java has a really deep folder structure. Do anyone do the same as I ?
 


Edited by ZwodahS, 23 July 2014 - 04:00 AM.

Check out my blog at zwodahs.github.io and zwodahs.itch.io/


Sponsor:

#2 Tribad   Members   -  Reputation: 970

Like
0Likes
Like

Posted 23 July 2014 - 04:15 AM

Putting header files into a include folder has the advantage that you have all interfaces to your modules in a single place, like /usr/include and /usr/local/include on UNIX style systems. To make the software available to others, maybe as a library gives you a  more simple way to find the header files to the libraries.

 

But at the end I suspect that it is up to your personal feeling about how to handle header files.



#3 Bacterius   Crossbones+   -  Reputation: 11541

Like
4Likes
Like

Posted 23 July 2014 - 04:50 AM

They are not mutually exclusive. You can have a main src or include folder which then branches off into a deep (but not too deep) file tree, with your modules neatly organized in separate files and folders. This is what I tend to do myself. In any case, if you are not designing a library or other code that could be reused by people other than you, I would just use whatever works best for you, such organizational concerns are not usually a major problem except to grumpy packagers used to doing things "their way" smile.png . Probably many of the large open source projects that you have seen have bureaucratic or architectural requirements (by virtue of being very large, or having lots of users and contributors) that would be very inappropriate in a smaller project, so many of the things you see in them would seem very strange from your perspective (though src/include is not really among them, but just saying). I don't think there is a widely accepted standard in C++ anyway, as long as your build system does not grow uncontrollably in complexity underneath you, you should not worry about it too much. C++ doesn't have a universal style guide that almost everybody follows like Java or C# do, far from that.

 

Some styles I've seen are "headers in include, source code in src", "only public headers in include, private headers and source code in src", "everything in src", "code dump with no folders at all (perhaps with e.g. a visual studio solution which already encodes the folder structure)", and so on... to be fair I do mostly C and not much C++, and I am personally not too comfortable with the idea of putting actual implementation code inside an "include" folder like a lot of the C++ projects seem to be doing with the advent of header-only libraries and templates (yes, I know it's not strictly required if you forward declare the different templated types you'll be using, but few bother to do that). But it's really no big deal - we are not machines, and can adapt when things don't go 100% as we expect. Really, it just goes to show that there is really no consensus on the right way to do it.

 

In any case, I can give a few insights on what I expect from a freshly checked out code repository:

 

* as a user (for libraries and other)

 

- is there an obvious build/install script (e.g. a solution file for visual studio for windows, a makefile or cmake/scons/autohell script for linux, a codeblocks project, etc..)?

- if not, is there a readme or install.txt I can look at?

- no? well, I don't know how to use it, if it's small enough and license permitting I might copy the source and headers inside my own code.. provided I can find them, e.g. an include or src folder

- if not, I give up and check out another library

 

* as a developer (contributing/etc)

 

- if the build system is a bit complex or there are things I should know or configuration options, are there notes about that somewhere? (not needed for small programs or obvious instructions e.g. a plain makefile)

- is it easy to build the software after changing code? does it make sure to always rebuild what needs to be (and, preferably, only what needs to be)?

- does it build out of source, or at least doesn't spew .o/.obj files everywhere in the source folder?

- are there tests I can run after making nontrivial changes?

 

As long as your project package provides these things, I don't see any problem. I've certainly seen far worse and I'm sure others have too.


“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”


#4 Karsten_   Members   -  Reputation: 1801

Like
0Likes
Like

Posted 23 July 2014 - 04:51 AM

Nested source layout seems to have two problems:
 
1) Includes may have to still be relative i.e #include "../../player/LeftHand.h" which may get a little bit messy and a pain if you decide to move the project structure.
2) At work when we used Unity we had an issue with locating scripts (quickly). A location that makes sense to one person does not to another. We decided to have all game script files in the same directory, all library scripts in their own directory. So much easier.
 
Note that Visual Studio provides structures in the IDE call "filters". Even though these appear to be nested, they only point to files which are all in the same directory. This may be the best of both worlds.
 
I recommend nesting source only if they are unique to a lib or .exe such as
 
mygame
- bin
  - game.exe
- lib
  - libplatform.a
  - libnetcode.a
  - libimageloader.a
- src
  - platform
    - *.cpp *.h
  - game
    - *.cpp *.h
  - netcode
    - *.cpp *.h
  - imageloader
    - *.cpp *.h
And then -Isrc/platform -Isrc/netcode -Isrc/imageloader so that library headers can be included using < >.

Edited by Karsten_, 23 July 2014 - 07:31 AM.

Mutiny - Open-source C++ Unity re-implementation.
Defile of Eden 2 - FreeBSD and OpenBSD binaries of our latest game.


#5 BitMaster   Crossbones+   -  Reputation: 5803

Like
0Likes
Like

Posted 23 July 2014 - 04:51 AM

Personally I'm never putting my headers into a different directory. The only point to do that would be for publishing just the headers for a library I want to publish, but I would rather use CMake or some other build tool to copy the relevant headers from the source directory to a published include directory when needed.

#6 Bacterius   Crossbones+   -  Reputation: 11541

Like
0Likes
Like

Posted 23 July 2014 - 04:55 AM


1) Includes may have to still be relative i.e #include "../../player/LeftHand.h" which may get a little bit messy and a pain if you decide to move the project structure.

 

I would suggest to not include files relative to the location of the source file or whatever, that is just asking for trouble in my opinion. Always include files from a base relative directory (e.g. project root, or more likely the "include" folder) and the problem disappears.


“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”


#7 Tribad   Members   -  Reputation: 970

Like
0Likes
Like

Posted 23 July 2014 - 05:04 AM

Using relative includes is a good choice to prevent many -I<include dir> compiler parameters. This way you can go inside a subdir with sources and start the compiler/make in there without thinking about where you are and how your compiler include parameter must look.

 

But... in fact it is awesome to handle if you move a module around.

 

Because I use UML with a code generator that produces the include statements I do not think about the positioning. It is always right and works, even if I move around the modules in the model.



#8 ZwodahS   Members   -  Reputation: 483

Like
0Likes
Like

Posted 23 July 2014 - 05:23 AM

Wow that is a lot of feedback :P. Thanks a lot.

 

I will think about this more before converting my projects.

 

 


1) Includes may have to still be relative i.e #include "../../player/LeftHand.h" which may get a little bit messy and a pain if you decide to move the project structure.

 

I would suggest to not include files relative to the location of the source file or whatever, that is just asking for trouble in my opinion. Always include files from a base relative directory (e.g. project root, or more likely the "include" folder) and the problem disappears.

 

 

So instead of relative includes, what would be a good way if I don't want a centralized include folder ?

I have this problem recently when I was reorganizing my files and I need to update quite a few of the includes.


Check out my blog at zwodahs.github.io and zwodahs.itch.io/


#9 Bregma   Crossbones+   -  Reputation: 6169

Like
3Likes
Like

Posted 23 July 2014 - 05:32 AM

I work with oodles of free software projects.  I've seen plenty with a separate includes/ directory and many that have them combined.  I've seen many with a deep or broad hierarchy and the same with everything dumped into a single subdirectory.  Technically it makes no difference and there is no de facto or de jure standard, it's entirely up to the taste of the most vocal or dominant developer.
 
Since packaging project source inevitably means installing into a staging directory, that isn't relevant.  Since installing means copying out of the sources into an installation directory, that's not relevant.
 
What is relevant is when someone comes along to try and read and understand the code, it's a lot easier when there isn't a separate include/ directory in the project, and the header and other sources files are all combined in one hierarchy.  I've noticed the most vocal proponents of the separate include/ hierarchy tend to be those who spend no time maintaining other people's code.  There is also no argument that in larger projects readability is improved by namespacing components into separate subdirectories and all include references are relative to the top of the hierarchy.  If each component produces a static convenience library (or, if required, a shared library) that also makes your unit testing easier.


Stephen M. Webb
Professional Free Software Developer

#10 BitMaster   Crossbones+   -  Reputation: 5803

Like
0Likes
Like

Posted 23 July 2014 - 06:17 AM

Using relative includes is a good choice to prevent many -I<include dir> compiler parameters. This way you can go inside a subdir with sources and start the compiler/make in there without thinking about where you are and how your compiler include parameter must look.


I would avoid relative includes if at all possible and rather use something like CMake to generate my makesfiles then.

#11 Tribad   Members   -  Reputation: 970

Like
0Likes
Like

Posted 23 July 2014 - 07:05 AM

Avoiding lots of search pathes on the command line has the benefit that it is clear what version of a header file is used and you need not read hundreds of -I parameters with long pathes to find at which point something goes wrong.

 

But as I already said. It is always alot of work if you move a module around.



#12 Karsten_   Members   -  Reputation: 1801

Like
1Likes
Like

Posted 23 July 2014 - 07:41 AM

So instead of relative includes, what would be a good way if I don't want a centralized include folder ?
I have this problem recently when I was reorganizing my files and I need to update quite a few of the includes.


Unless you are making reusable libraries as part of your project, I would recommend a single folder for both your src and header files. i.e a single .exe means I would create a single src directory. If you find this folder simply has too much source code files in, then this might even suggest that you need to break your project up into multiple separate libraries (in which case they would get their own src directories (containing .cpp and .h).

So since these libraries and binaries are separate projects, you could say that I don't do any nesting in my projects. Some places where you may be tempted however is if some code is completely standalone from the rest of the project (i.e so no #include "../" needed since it has no dependence on other headers). If a part of a project is also in a separate namespace then you may also want to nest, however often parts in a nested namespace still require ../headers and I do typically try to avoid this pattern.

One system that I have found to be very effective is the following (I use cmake but this should work with many build systems). Imagine a folder structure as follows:
 
proj/
  src/
    game/
    foolib/
    barlib/
If I specify on the command like -Isrc, this means that anywhere in the game source code, I can do
 
  #include <foolib/foolib.h>
If foolib has a dependency on barlib, I can do in the foolib code:
 
  #include <barlib/barlib.h>
This means that you can separate your project into logical libraries (and separate .cpp / .h directories) and yet still be able to reference the correct headers you need.

Whats quite useful about this system is that if barlib was really made to be a standalone library, I could have an installer script like:
 
# mkdir /usr/local/include/barlib
# cp -r src/barlib/*.h /usr/local/include/barlib
# cp lib/barlib.a /usr/local/lib/
And now any project on my computer can access the barlib.h in exactly the same way as when it was part of my project.

Edited by Karsten_, 23 July 2014 - 07:51 AM.

Mutiny - Open-source C++ Unity re-implementation.
Defile of Eden 2 - FreeBSD and OpenBSD binaries of our latest game.


#13 BitMaster   Crossbones+   -  Reputation: 5803

Like
0Likes
Like

Posted 23 July 2014 - 08:00 AM

Avoiding lots of search pathes on the command line has the benefit that it is clear what version of a header file is used and you need not read hundreds of -I parameters with long pathes to find at which point something goes wrong.


Well, in general I set exactly one include directory for my project (excluding 3rd party libraries). Every file can then simply include what it needs using <mytool/file.h> or <mylibrary/file.h>. CMake just simplifies doing that because every sub-makefile is aware of that include directory without any work on my part. An added benefit is that you immediately see which library/subproject an include is from.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS