Project hierarchy guidelines

Abstract

One thing that every growing software project has to deal with at some point is organizing files in their repository: where to put source files? Where to put tests? Packaging templates (.spec, debian/control)? Build scripts? Project guidelines?

What I've seen most often is generally one of these:

Each of above approaches has its cons and (arguably) pros, the mere decision which approach to apply is not easy, so one easily gets into a decision paralysis.

This document is an attempt to help people avoid that and get at least some starting point when putting things together.

Guidelines

Root (README et al.)

It's good to keep as little files here as possible, but few names have already become de-facto standard.

Every decent project has a README file in the root folder. You can name it README.md, README.rst, but it should be the first thing everyone reads. Normally, a brief introduction and installation instructions, unless they are already provided under INSTALL file.

Among other common files here are LICENSE, Makefile, CHANGELOG or similar files that are chiefly related to a project as a whole.

src

Everything that is supposed to be (directly or in some "built" form) deployed on the target host goes under src.

Under this folder, it makes sense to have files divided in sub-folders named reminiscent to the target paths. For example, host configuration files should be under src/etc, library source files under src/lib, future binaries under src/bin, future manpages to src/man...

Note that it does not matter whether there is some significant build procedure to happen; it's OK if most of the files here are just verbatim copies ready to be deployed to the target.

tests

Your test suite goes here. How to structure files under this directory will most probably depend on the test framework you use.

relics

Place for locally ran tests to drop any results, reports and intermediate files that would be useful for investigating test failures.

Subdirectories here should bear a timestamp in a human-readable and sortable timestamp format (such as ISO 8601).

Note that normally this directory will never exist in a freshly cloned repository and it's likely to be excluded from version control system via file such as .gitignore.

notes

Documentation related to your project. Evertything from guidelines to newcomer howtos, style guides, design notes, philosophy articles...

utils

Any build scripts and utilities that are only useful for your project developers, maintainers and testers.

packaging

Templates to help package maintainers. Templates for RPM SPEC files, debian control directories or similar data can live here.

Note that in many cases distributions like Debian or Fedora may not be able to directly use these files, but they can be a good start for e.g. creating unofficial .deb files.

MKit already provides features that can help generate such files.

Example

A "living" example: shellfu:

.
├── LICENSE             # \
├── Makefile            #  Pretty much standard files...
├── README.md           # /
├── mkit.ini            # <- MKit meta-data file
├── notes               # <- my design notes, although
│   └── style.md        #    most are still in my head :)
├── packaging
│   ├── debian          # \
│   │   ├── changelog   #   only used for ad-hoc, testing and
│   │   ├── control     #   alpha RPMs and .deb's
│   │   └── ...         #   (so far, probably for good)
│   └── shellfu.spec    # /
├── relics
│   ├── relics-inigrep_inigrep-20161202-073432
│   │   ├── TF_ENUMERATED_SUBTESTS
│   │   ├── TF_FILTERED_SUBTESTS
│   │   ├── TF_RUN
│   │   ├── oracle      # \
│   │   │   └── ...     #   relics are now huge since 
│   │   ├── result      #   I ran a lot of tests recently
│   │   │   └── ...     # /
│   │   └── test
│   │       └── ...
│   └── relics-shellfu_api-20161202-081440
│       └── ...
├── src
│   ├── bin                     # \
│   │   ├── shellfu-doc         #   here most of the "meat" lives,
│   │   └── shellfu-get.skel    #   only about two files really need
│   ├── complete-devel.bash     #   any "building"
│   ├── complete.bash           #
│   ├── include-bash            #   notice that tree here does
│   │   └── ...                 #   not attempt to strictly follow
│   ├── include-sh              #   final placement, just hinting
│   │   └── ...                 #   is enough
│   └── shellfu.sh.skel         # /
├── tests                   # \
│   ├── TF_HEADER           #   another "huge" directory
│   ├── inigrep_inigrep     #   structure, the test suite
│   │   ├── TF_RUN          #
│   │   ├── oracle          #   hierarchy is influenced by TFKit
│   │   │   └── ...         #   which itself is actually embedded
│   │   └── test            #   under *utils* directory below
│   │       └── ...         # /
│   └── ...                 #
└── utils           # \
    ├── mkit        #   all build scripts live here; actually just
    │   └── ...     #   MKit and TFKit; note that TFKit lives apart
    └── tfkit       #   from the suite (they meet often, though ;))
        └── ...     # /
Mastodon
published by mdpublish, 2024-06-13