Table of Contents:
The layout and basic structure of a project’s source directory needs to be done when the project is created. If done well, with thought put into future maintainability and scalability of the build system, little maintenance time will be required on the build system in future.
Summary
- Follow the standard root directory layout so users of the project can find information where they expect. (Root directory layout)
- Ensure the project and each source code file is clearly licenced. (Licencing)
- Do not commit generated files to
git
. (Generated files) - For libraries, separate public and private dependency lists using
AX_PKG_CHECK_MODULES
. (Dependency management) - For libraries, ensure they are completely parallel installable with other API-incompatible versions of the same library. (Parallel installability)
Root directory layout
In the root directory of a module’s repository, the following files should exist:
AUTHORS
: Should contain a contact address which is unique to the module, but which doesn’t necessarily have to be a real person. It could be a catch address like[module] maintainers <[module]@apertis.org>
.NEWS
: Should have a section for each release, in a format similar to this: 1- All API changes and additions should be clearly listed so that developers using the library know how to update their code.
- All major changes should be clearly listed so packagers know what to test.
- Updates to translations should be listed, unless the module doesn’t have translations.
README
: Should give a description of the module, what it does, and potentially a list of its dependencies (if such a list could be kept up to date).COPYING
: Should be a verbatim copy of the module’s licence, the MPLv2.[project-name]/
(libraries) orsrc/
(programs): Location for all source code, including header files. Header files should not be put in a separateinclude/
directory, as that separates them from their associated C files, making maintenance a little harder. Libraries should have their source code in a directory named after the project so that headers can be universally included using#include <[project-name]/header.h>
for namespacing reasons.
Licencing
As well as a valid COPYING file, in order for a
module to be correctly licenced, it should be clear which files the licence
applies to. Therefore it is necessary to put a brief copyright header at the
top of each source code and header file, and in README
. This is in addition
to having a COPYING
file.
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
In source and header files, this should go immediately after the
file’s vim modeline.
In the README
it should go in a ‘Licensing’ section.
For more information on licensing, see the licensing guide.
Generated files
Any file which is generated by the build system (that is, by autogen.sh
,
automake
or make
) should not be committed to git. Doing so makes the
repository larger unnecessarily, results in spurious changes in people’s
commits as the generated files change, can cause conflicts on checkout, and can
result in stale files if the build system always uses an out-of-date copy of
the generated file from git
.
Generated files should be ignored by git
; this can be automated by using
git.mk
in each module. Ideally, the
output of git status
should be empty for a module which has been checked out,
not modified, and then built. git.mk
automatically ignores files listed in
CLEANFILES
(and the other automake cleaning variables), so if generated files
are correctly cleaned, they should be correctly ignored by git
.
Generated files include those generated manually by programmers, using
gdbus-codegen
for example. Instead of generating such files manually, rules should be added
to the Makefile.am
to use gdbus-codegen
at build time and automatically
generate the files.
Other typical files which are automatically generated and which should not be
in git
:
ChangeLog
- All files in
m4/
except in-tree macros from the autoconf-archive - All files in
config/
po/ChangeLog
po/Makefile.in.in
po/POTFILES
(but leavePOTFILES.in
in git)po/stamp-it
Dependency management
Libraries (but not applications) have to be careful which of their dependencies are exposed publicly (referenced in the library’s public header files). Public dependencies need to be kept separate from private dependencies, as they need to be handled differently for shared and static linking. Private dependencies are not needed for dynamic linking, but are needed for static linking. By removing them from the dynamic link command, over-linking is prevented.
pkg-config has support for public and private dependencies in the form of its
Requires
and Requires.private
keys.
Use the
AX_PKG_CHECK_MODULES
macro from autoconf-archive
instead of the normal pkg-config PKG_CHECK_MODULES
macro to automatically
support public and private dependencies, as explained in this article:
A checklist for writing pkg-config files.
Parallel installability
All public libraries should be designed to be installable in parallel with other API-incompatible versions of the same library. This has little impact at the start of a project, but is very important later in the project’s lifetime if a large API break is made. It is hard to port every user of a library from the old API to the new one, so it is necessary to support installation of the two versions of the library in parallel, without them conflicting. Building in support for this kind of parallel installation is much easier to do at the start of a project than it is to do retroactively.
This is explained in detail in this article on parallel installability. The key point is to include the project’s major package version number in its library name everywhere the library is installed on the file system — in the binaries, the header include paths, and the pkg-config name and filename.