cqfd provides a quick and convenient way to run commands in the current directory, but within a Docker container defined in a per-project config file.
This becomes useful when building an application designed for another Linux system, e.g. building an old embedded firmware that only works in an older Linux distribution.
Just follow these steps:
- Install cqfd (see below)
- Make sure your user is a member of the
docker
group - Go into your project's directory
- Create a .cqfdrc file
- Put a Dockerfile and save it as .cqfd/docker/Dockerfile
- Run
cqfd init
Examples are available in the samples/ directory.
cqfd will use the provided Dockerfile to create a normalized runtime build environment for your project.
To build your project from the configured build environment with the default build command as configured in .cqfdrc, use:
$ cqfd
Alternatively, you may want to specify a custom build command to be executed from inside the build container.
$ cqfd run make clean
$ cqfd run "make linux-dirclean && make foobar-dirclean"
When cqfd
is running, the current directory is mounted by Docker
as a volume. As a result, all the build artefacts generated inside the
container are still accessible in this directory after the container
has been stopped and removed.
The release command behaves exactly like run, but creates a release
tarball for your project additionally. The release files (as specified
in your .cqfdrc
) will be included inside the release archive.
$ cqfd release
The resulting release file is then called according to the archive
template, which defaults to %Po-%Pn.tar.xz
.
You may also want to build a specific build flavor, for a regular build or a release. To do so use the -b option, for example:
$ cqfd -b debug run
When building with a flavor, as when building a regular project, the
run
option can be omitted.
The .cqfdrc file at the root of your project contains the information required to support project tooling. samples/dot-cqfdrc is an example.
Here is a sample .cqfdrc file:
[project]
org='fooinc'
name='buildroot'
[build]
command='make foobar_defconfig && make && asciidoc README.FOOINC'
files='README.FOOINC output/images/sdcard.img'
archive='cqfd-%Gh.tar.xz'
org
: a short, lowercase name for the project’s parent organization.
name
: a short, lowercase name for the project.
Generated Docker images for your project will be named $org_$name.
command
: the command (or list of commands) to be executed when cqfd is
invoked. This string will be passed as an argument to a classical
bash -c "commands"
, within the build container, to generate the
build artefacts.
files
: an optional space-separated list of files generated by the
build process that we want to include inside a standard release
archive.
archive
: the optional name of the release archive generated by
cqfd. You can include environment variable names, as well as the
following template marks:
%Gh
- git short hash of last commit%GH
- git long hash of last commit%D3
- RFC3339 date (YYYY-MM-DD)%Cf
- current cqfd flavor name (if any)%Po
- value of theproject.org
configuration key%Pn
- value of theproject.name
configuration key%%
- a litteral '%' sign
By default, cqfd will generate a release archive named
org-name.tar.xz
, where 'org' and 'name' come from the project's
configuration keys. The .tar.xz, .tar.gz and .zip archive formats are
supported.
For tar archives, setting tar_transform=yes
will cause all files
specified for the archive to be stored at the root of the archive,
which is desired in some scenarios. This feature is not supported with
.zip archives.
flavors
: the list of build flavors (see below). Each flavor has its
own command just like build.command.
In some cases, it may be desirable to build the project using variations of the build and release methods (for example a debug build). This is made possible in cqfd with the build flavors feature.
In the .cqfdrc file, one or more flavors may be listed in the
[build]
section, referencing other sections named following
flavor's name.
[debug]
command='make DEBUG=1'
files='myprogram Symbols.map'
[build]
command='make'
files='myprogram'
flavors='debug'
A flavor will typically redefine the keys of the build section: command, files, archive.
Flavors from a .cqfdrc
file can be listed using the flavors
argument.
The following environment variables are supported by cqfd to provide the user with extra flexibility during his day-to-day development tasks:
CQFD_EXTRA_VOLUMES
: A space-separated list of additional volume
mappings to be configured inside the started container. Format is the
same as (and passed to) docker-run’s -v option.
CQFD_EXTRA_HOSTS
: A space-separated list of additional host
mappings to be configured inside the started container. Format is the
same as (and passed to) docker-run’s --add-host option.
CQFD_EXTRA_ENV
: A space-separated list of additional environment
variables to be passed to the started container. Format is the
same as (and passed to) docker-run’s -e option.
In some conditions you may want to use an alternate config file with cqfd. This is what the -f option is for:
$ cqfd -f .cqfdrc.test
When cqfd runs, a docker container is launched as the environment in which to run the command. Within this environment, commands are run as the 'builder' user. So that this user has access to local files, the current working directory is mapped to ~builder/src/.
The local ~/.ssh directory is mapped to the corresponding directory in the build container i.e. ~builder/.ssh. This effectively enables SSH agent forwarding so a build can, for example, pull authenticated git repos.
Note that it may be helpful to specify the local user name in the .ssh/config file as this isn't the default on the builder e.g.
$ echo "User $USER" >> ~/.ssh/config
To use cqfd, ensure the following requirements are satisfied on your workstation:
-
Bash 4.x
-
Docker
-
A
docker
group in your /etc/group -
Your username is a member of the
docker
group -
Restart your docker service if you needed to create the group.
The cqfd script can be installed system-wide.
Install or remove the script and its resources:
$ make install
$ make uninstall
Makefile honors both PREFIX (/usr/local) and DESTDIR ([empty]) variables:
$ make install PREFIX=/opt
$ make install PREFIX=/usr DESTDIR=package
The codebase contains tests which can be invoked using the following command, if the above requirements are met on the system:
$ make tests
CQFD stands for "Ce qu'il fallait Dockeriser", french for "what needed to be dockerized".