Page 1 of 1

project directory layout

Posted: Tue Apr 06, 2010 5:51 pm
by NickJohnson
I've been frequently switching around the directory structure of my project's source code in an attempt to make it neater. However, I haven't been able to really settle on something, but I do have some ideas. I would like to hear what other people think about what the ideal directory structure is.

Here is my general layout. The entire project, which consists of a combination of libraries and programs, has a directory for each at its root. Directories beginning with "lib" are libraries, and are named for the libraries they produce. Program directories are also named for what they produce. Within each library directory, there is a directory named "inc" that contains header files that will be installed into the system; all other directories, if any, contain source. The same goes for programs, except that the header files in "inc" are not installed.

My main problem is that I use the -Idirectory option on my compiler to make programs think that their headers are system headers, for brevity. If I didn't, header foo.h would be either "../inc/foo.h" or "inc/foo.h" (instead of <foo.h>) depending on the source file, and that looks ugly and prevents rearranging source easily. The line between programs and libraries is also blurred on my future system, so I may have to install some of those headers into the system as well.

I was thinking of eliminating source subdirectories altogether so local headers could be mixed with source ("foo.h" is as good as <foo.h>), but that seems to be messy. I have been slowly adopting the practice I saw in Solar's pdclib where every function is by itself in an equivalently named source file, which would probably give enough organization even with a flat structure; this is already nearly complete in my C library and kernel, but nowhere else. Does this seem like a sustainable solution?

If anyone finds another problem with my current layout or an obviously better solution from their own experience, it would be greatly appreciated.

Thanks,
Nick Johnson

P.S. you can see the actual project at the link in my sig, if my description was unclear.

Re: project directory layout

Posted: Tue Apr 06, 2010 6:58 pm
by Gigasoft
If every function resides in its own source file, you'll end up with hundreds of source files and it will be a hassle to find anything, so wouldn't recommend that. I prefer to put everything that belongs to the same logical division of a program in its own source file. For example, everything that has to do with the FAT file system goes in fat.asm, and generic system functions go in system.asm. This makes editing easier. One good question to ask is, would one ever think of using this source file on its own in another project? If the answer is no (for example, if it only contains an IRQ handler belonging to some driver, or a function that deallocates memory), it would probably be easier in the long run to put its contents in the same file as the rest of the functions it belongs to.

I tend to keep all the include files in the same directory as the source files that are related to them. This saves me from typing directory names when I want to edit one or the other. With the source file organization above, and an additional goal I have stating that every separate component should only communicate with other components using public documented interfaces, there will be almost no private include files, if any. Any private include files can be put in a subdirectory of the directory containing the other files, so that they are easily excluded when packaging the files for a release.

Re: project directory layout

Posted: Tue Apr 06, 2010 7:09 pm
by JackScott
NickJohnson wrote:I was thinking of eliminating source subdirectories altogether so local headers could be mixed with source ("foo.h" is as good as <foo.h>), but that seems to be messy. I have been slowly adopting the practice I saw in Solar's pdclib where every function is by itself in an equivalently named source file, which would probably give enough organization even with a flat structure; this is already nearly complete in my C library and kernel, but nowhere else. Does this seem like a sustainable solution?
The reason for that, as far as I am aware, is that when some linkers link in a function from a code archive (.a) they can only pull a whole object file, not just one function from that object file. As an example, say you wanted to include strcpy() from PDCLIB into your program. If Solar had put every string function into one C file, you would be forced to link in all the string functions, even if you only wanted one. So it makes sense for libraries to do one function per file. Whether that makes sense for a kernel (at least for the same reason) is a different matter.

Re: project directory layout

Posted: Tue Apr 06, 2010 8:19 pm
by NickJohnson
I know that static linking was at least one of the reasons for the one-function-per-file thing (I think it's explained on the PDClib site). Still, because my functions are generally named by subsystem (e.g. page_get or thread_alloc), it's very easy to see the organization with a single directory listing, and headers still bind together groups of functions. I can see how that would get insane with hundreds of files, but with a couple dozen, it's not bad. One of the goals of my OS is to have an extremely modular base system, with libraries and programs that are only a few thousand lines long, so it may work especially well for me. Is there any problem with that layout other than when a piece of the base system grows to hundreds of functions?

I suppose it wouldn't be too hard to keep local includes with source for normal programs, but most parts of my kernel are at least interdependent because of typedefs and structs in header files. Assuming I keep a directory structure, is it better style to make all files consistently include with "../inc/foo.h", or include "foo.h" when in the foo directory and "../foo/foo.h" when in other directories?

Re: project directory layout

Posted: Tue Apr 06, 2010 8:43 pm
by Gigasoft
One of the problems with having many different source files implementing parts of the same functionality is having to constantly switch between editor windows when working on them, especially considering that you may also need to make changes to other system components (each with dozens of source files) during the course of the work.

For a kernel, perhaps it would be better to have all the include files that are meant for use by other components in a single location and have this directory in the include path.

Re: project directory layout

Posted: Tue Apr 06, 2010 11:32 pm
by Solar
A setup I've seen at work had "lib units" and "bin units", with a setup for lib units that was actually three-fold for lib-units:

Code: Select all

<unit>/src/*.c
<unit>/inc/*.h
<unit>/pub_inc/*.h
./inc/ contained headers used by the library internally, and was set as include directory using the -I option in the makefile, so library source could include the headers without having to prefix any directories.

./pub_inc/ contained headers to be used by client code (i.e., the API of the lib to be used by bin-units). Building the lib-unit also copied the headers from <unit>/pub_inc/ to a global includes/<unit>/ directory. Pseudocode to explain:

Code: Select all

rm -rf includes/<unit>
mkdir includes/<unit>
cp <unit>/pub_inc/* includes/<unit>/
That includes directory was then set by the -I option of the compiler when building bin-units. The effect was that client code would use:

Code: Select all

#include <unit/header.h>
I thought that setup was pretty neat, divided internal headers and external ones as well as tucking away all sources into a seperate subdirectory.

In the end, I believe every project has its own "best" setup. The "one function, one file" setup I used for PDCLib would be inappropriate for a single-purpose library, for example, where every function is heavily dependent on each other.

Re: project directory layout

Posted: Wed Apr 07, 2010 1:20 am
by Love4Boobies
Not even Java goes that far :) Though, probably inspired by Java, Pedigree has one source file per class. You could perhaps try that; it makes sense for a variety of reasons, including (but not limited to) linking...

Re: project directory layout

Posted: Wed Apr 07, 2010 7:17 am
by Solar
Well, for the OO languages it's pretty clear: One class per file, file and class named identically. Actually, violating that rule makes you an instant enemy of myself. ;-)

Re: project directory layout

Posted: Wed Apr 07, 2010 7:49 am
by Love4Boobies
Oops, I thought NickJohnson was a C++ guy. Just checked the link in his signature and he is using C so nevermind my last post. #-o