lw-build-system Instructions ======================================================================== Introduction ------------ The build system is a set of shell scripts used to build various types of object file. Each project consists of one or more modules. Source files (committed to the repository) live in "src", with one subdirectory per module. Object files (or other volatile output) lives in "obj". Cleaning is simply a case of deleting the "obj" directory. Only a minimal part of the build system is committed to the repository for each project; enough to build the project if it is checked out or downloaded as a tarball. The rest of the build system (needed for actual development) is installed as symlinks, so that changes to the build system do not necessarily require changes to the repository. Creating a New Project ---------------------- Instantiating a new project is done with `lw-build-system/create.sh'. Simply pass the project name as the first argument. (It can be called with no arguments to display usage). The `~/.lwbuildrc' file, created on the first call of the project creation script, contains some variables which are used when instantiating the empty project and module templates. The `config' file in the root of the project directory is where user-editable variables live. Variables are generally only set here if they are not exported in the environment; this allows variables to be overridden in a wrapper script, with the defaults specified. This might be a good point to run `git init-db', if you intend to use the git SCM system. Instantiating Modules --------------------- (This can only be done if the development symlinks are installed). The `scripts/module-create.sh' script will allow the instantiation of new modules. Running it with no arguments will display usage; generally, it will take the module type, language, and name. The name is used directly as `src/${name}', and will also be the name of the output binary. As modules are instantiated, they add any required arguments (e.g. ${CFLAGS} or ${BINDIR}) into the `config' file. The `src/${name}/build.*' files may be edited to alter build behaviour. This includes adding arguments to the C compiler. Variables set in `config' are available when these scripts are run. There are a few conventions of note. Anything that wishes to link against external libraries will usually use two variables in `config' (libname_CFLAGS and libname_LIBS). If these are produced by running $(libname-config --cflags) and $(libname-config --libs), then lines suitable for `config' can be produced by running `scripts/config-printflags.sh libname'. An application module has an EXTRAS variable in its build.app into which the libname flags are placed (in addition to any others). A library module will need to export dependency information; this is done by changing the module_DEP_CFLAGS and module_DEP_LIBS flags in `build.lib'. The dependency information will be placed into the lib-config executable installed along with the library. Sometimes, it is useful to have compile-time options. Conventionally, these will be placed into the `config' file, and will often have a name such as CONFIG_DISABLE_FOO. Building -------- Individual modules can be built with `./make.sh ${name}'. They can also be built by category; see `src/${name}/build.*'. The part of the filename after `build.' can also be passed to `./make.sh'. This allows, for example, all applications to be built (`./make.sh app'); or only libraries to be installed (`./make.sh install-lib'). Setting the environment variable VERBOSE to 1 before running make.sh will display some additional tracing output. Versioning and Tagging ---------------------- The `version' file in the top level of the project directory contains the overall package version. This information is exported to C applications and libraries via the preprocessor as VERSION and VERSION_{MAJOR,MINOR,MICRO}. Library modules have a `soversion' file, entirely independent of the top-level version, which is used to create symlinks as well as set the soname of the library. The soname depends only on the major and minor version, meaning that the micro version number can be bumped without changing the soname. `scripts/version.sh' can be run to bump version numbers automatically. If the project is a git repository, it can also be used to create tags and push changes to a central repository. The version script takes a number of commands, and executes them in order. The following commands may be used: major, minor, micro Bump the version number in the top-level `version'. Bumping the minor version will clear the micro version; bumping the major version will clear minor and micro. libmajor, libminor, libmicro (1 argument) Bump the soversion number in a library's `soversion', with the same semantics as major/minor/micro. The argument is the library module's name. tag (git only) If this is a git repository, creates a tag based on the contents of `version'. push (git only) If this is a git repository, does a `git push' as well as a `git push --tags'. This is a good way to ensure that any tags you create are pushed to a central repository (this normally needs to be done separately). Creating tarballs ----------------- (This only works for git repositories). `scripts/release.sh' can be run to create a tarball of the project. It takes two arguments: the first is the version number (or git tag) of the version to release, and the second the output directory. This will create a source tarball, a documentation tarball if a doxygen module is detected, and will also attempt to sign the tarballs with gpg (although it is not a fatal error if this step fails). Upgrading build system ---------------------- Sometimes, the nonvolatile parts of the build system (the static parts that are committed to the repository) need to be upgraded as well. There is a script to do this in the lw-build-system repository. From the project base directory, run the script `/path/to/lw-build-system/update.sh'. This only works if symlinks are installed. It will create a patch file, which you should edit before applying. Unfortunately, the upgrade process is not perfect and will not detect legitimate changes you have made to files such as `config' and modules' `build.*' files. You will need to manually edit the patch to revert false positives.