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

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) or src/ (programs): Location for all source code, including header files. Header files should not be put in a separate include/ 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 leave POTFILES.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.

External links