UCCL - Uniform C Code Layout #
A Uniform code layout facilitates a developer’s access to an unfamiliar code base, saving valuable time and effort. At the same time it makes easier to integrate and reuse different projects.
This layout proposal uses symbolic links, called symlinks for short, to provide a uniform method for access between projects. Symbolic links are used only at directory level, not at file level.
- Package ≡ Repository ≈ Library
- A unit of software that resides in a unique source control repository. In general a package generates a binary library, unless it is a header-only package. All files in a package are located in one directory (that can have any number of sub-directories).
- Development tree
- A directory that contains all packages. It’s location is arbitrary but we will assume it is indicated by the
- Files, other than libraries produced by a package. These can include programs, data files, etc.
Layout Description #
Following is a semi-formal description of the proposed layout.
1. Basic rules #
1.1 Location of header files #
All header files of a package are placed in a subdirectory of the package directory. The name of the subdirectory is
1.2 Location of API header files #
All header files that compose the public API of a package are located in a subdirectory of the
include/ directory. The name of the subdirectory must be the same as the package name.
1.3 Location of library files #
All library files are placed in the
lib/ subdirectory of
$DEV_ROOT directory. Each package directory contains a symbolic link, named also
lib/ to this subdirectory. Library variants for different platforms or configurations may be placed in different subdirectories. The naming scheme
<platform>/<configuration> is recommended.
With these basic rules, the layout of a package is like this:
2. References to other packages #
2.1 Location of external header files #
A package can reference another package by placing a symlink to its public API in the
include folder. The symlink has the same name as the referenced package.
Example: The package
Libraries created by other packages are implicitly visible in the
3. Other artifacts #
3.1 Location of executable artifacts #
Programs and related components are located in the
bin/ subdirectory of the
$DEV_ROOT directory. Packages that produce these artifacts as well as packages that need them, should have a symbolic link, also named
bin/ pointing to this location.
$DEV_ROOT/bincan be added to
PATHto make these programs accessible from anywhere.
4. Source #
4.1 Location of source files #
Source files are located in the
src/ folder of the package directory.
4.2 Referencing header files #
include/ directory of a package should be added to the compiler search path. If the layout rules have been respected, there should be no ambiguity or name clashing between the different header files.
Example: Consider a file
// Reference to a package_a API file #include <package_a/api.h> // Reference to a package_b API file #include <package_b/api.h> //Reference to a package_a internal header file #include <internal.h>
5. Other directories #
The following directories can appear at the top level in any package, in addition to the ones discussed before. None of them are required.
- Used for storing intermediate build artifacts (object files, symbols, etc.)
- Any data files required by a package.
- Documentation and documentation-related files.
- build scripts and other build-related files.
- Sample program files.
- Unit tests and other test files.
The following guidelines are born from experience with this layout.
Minimize the number of files at top level of a package. In general only well-known files (README, LICENSE, AUTHORS, etc.) should be kept at top level. This is not always possible as some toolchains require specific files to be also placed at top level.
Place files related to the used toolchain in a subdirectory of the
fab/directory, with a name that clearly indicates the toolchain used. Some suggested toolset names are:
clang/for CLang compiler
gcc/for GCC tools
msc/for Visual Studio C/C++ compiler
Use a scheme like
<platform name>/<toolset>/<configuration>for subdirectories of
lib/; keep the library name unchanged.
$DEV_ROOT/lib/x64/msc/debug/package_a.libthe library name created by
package_awhen compiled in debug mode for x64 platform using Visual Studio C/C++ compiler.
Some suggested platform names are:
Layout Summary #
|$DEV_ROOT/||Root of development tree|
|lib/||Directory of static link libraries|
|package/||Package root directory|
|fab/||Build scripts and related files|
|package/||Public package header files|
|lib/||Symlink to |