Creating and Managing Projects Once Hydra is installed and running, the next step is to add projects to the build farm. We follow the example of the Patchelf project, a software tool written in C and using the GNU Build System (GNU Autoconf and GNU Automake). Log in to the web interface of your Hydra installation using the user name and password you inserted in the database (by default, Hydra's web server listens on localhost:3000). Then follow the "Create Project" link to create a new project.
Project Information A project definition consists of some general information and a set of job sets. The general information identifies a project, its owner, and current state of activity. Here's what we fill in for the patchelf project: Identifier: patchelf The identifier is the identity of the project. It is used in URLs and in the names of build results. The identifier should be a unique name (it is the primary database key for the project table in the database). If you try to create a project with an already existing identifier you'd get an error message such as: I'm very sorry, but an error occurred: DBIx::Class::ResultSet::create(): DBI Exception: DBD::SQLite::st execute failed: column name is not unique(19) at dbdimp.c line 402 So try to create the project after entering just the general information to figure out if you have chosen a unique name. Job sets can be added once the project has been created. Display name: Patchelf The display name is used in menus. Description: A tool for modifying ELF binaries The description is used as short documentation of the nature of the project. Owner: eelco The owner of a project can create and edit job sets. Enabled: Yes Only if the project is enabled are builds performed. Once created there should be an entry for the project in the sidebar. Go to the project page for the Patchelf project.
Job Sets A project can consist of multiple job sets (hereafter jobsets), separate tasks that can be built separately, but may depend on each other (without cyclic dependencies, of course). Go to the Edit page of the Patchelf project and "Add a new jobset" by providing the following "Information": Identifier: trunk Description: Trunk Nix expression: release.nix in input patchelfSrc This states that in order to build the trunk jobset, the Nix expression in the file release.nix, which can be obtained from input patchelfSrc, should be evaluated. (We'll have a look at release.nix later.) To realize a job we probably need a number of inputs, which can be declared in the table below. As many inputs as required can be added. For patchelf we declare the following inputs. patchelfSrc 'Subversion checkout' https://svn.nixos.org/repos/nix/patchelf/trunk nixpkgs 'Subversion checkout' https://svn.nixos.org/repos/nix/nixpkgs/trunk officialRelease Boolean false system String value "i686-linux"
Release Set there must be one primary job check the radio button of exactly one job https://svn.nixos.org/repos/nix/nixpkgs/trunk
Building Jobs
Build Recipes Build jobs and build recipes for a jobset are specified in a text file written in the Nix language. The recipe is actually called a Nix expression in Nix parlance. By convention this file is often called release.nix. The release.nix file is typically kept under version control, and the repository that contains it one of the build inputs of the corresponding–often called hydraConfig by convention. The repository for that file and the actual file name are specified on the web interface of Hydra under the Setup tab of the jobset's overview page, under the Nix expression heading. See, for example, the jobset overview page of the PatchELF project, and the corresponding Nix file. Knowledge of the Nix language is recommended, but the example below should already give a good idea of how it works: <filename>release.nix</filename> file for GNU Hello { nixpkgs }: let pkgs = import nixpkgs {}; jobs = rec { tarball = { helloSrc }: pkgs.releaseTools.sourceTarball { name = "hello-tarball"; src = helloSrc; buildInputs = (with pkgs; [ gettext texLive texinfo ]); }; build = { tarball ? jobs.tarball {} , system ? builtins.currentSystem }: let pkgs = import nixpkgs { inherit system; }; in pkgs.releaseTools.nixBuild { name = "hello" ; src = tarball; configureFlags = [ "--disable-silent-rules" ]; }; }; in jobs shows what a release.nix file for GNU Hello would you like. GNU Hello is representative of many GNU and non-GNU free software projects: it uses the GNU Build System, namely GNU Autoconf, and GNU Automake; for users, it means it can be installed using the usual ./configure && make install procedure; it uses Gettext for internationalization; it has a Texinfo manual, which can be rendered as PDF with TeX. The file defines a jobset consisting of two jobs: tarball, and build. It contains the following elements (referenced from the figure by numbers): This specifies a function of one named arguments, nixpkgs. This function and those defined below is called by Hydra. Here the nixpkgs argument is meant to be a checkout of the Nixpkgs software distribution. Hydra inspects the formal argument list of the function (here, the nixpkgs argument) and passes it the corresponding parameter specified as a build input on Hydra's web interface. In this case, the web interface should show a nixpkgs build input, which is a checkout of the Nixpkgs source code repository. This defines a variable pkgs holding the set of packages provided by Nixpkgs. This defines a variable holding the two Hydra jobs–an attribute set in Nix. This is the definition of the first job, named tarball. The purpose of this job is to produce a usable source code tarball. The tarball takes an additional argument called helloSrc. Again, this argument is passed by Hydra and is meant to be a checkout of GNU Hello's source code repository. The tarball job calls the sourceTarball function, which (roughly) runs autoreconf && ./configure && make dist on the checkout. The buildInputs attribute specifies additional software dependencies for the job. This is the definition of the build job, whose purpose is to build Hello from the tarball produced above. The build function takes two additional parameter: tarball, which is meant to be the result of the tarball job, and system, which should be a string defining the Nix system type–e.g., "x86_64-linux". Again, these parameters are passed by Hydra when it calls build. Thus, they must be defined as build inputs in Hydra: tarball should have type Build Output, its value being the latest output of the tarball job, and system should be a string. The question mark after tarball and system defines default values for these arguments, and is only useful for debugging. The build job calls the nixBuild function, which unpacks the tarball, then runs ./configure && make && make check && make install. Finally, the set of jobs is returned to Hydra, as a Nix attribute set.
Building from the Command Line It is often useful to test a build recipe, for instance before it is actually used by Hydra, when testing changes, or when debugging a build issue. Since build recipes for Hydra jobsets are just plain Nix expressions, they can be evaluated using the standard Nix tools. To evaluate the tarball jobset of , just run: $ nix-build release.nix -A tarball However, doing this with as is will probably yield an error like this: error: cannot auto-call a function that has an argument without a default value (`nixpkgs') This is because no value was specified for the nixpkgs argument of the Nix expression. This is fixed by providing a default value for that argument in the Nix expression, which will allow nix-build to auto-call the function: instfead of writing { nixpkgs }:, we now write { nixpkgs ? <nixpkgs> }:. What it means is that, by default, the nixpkgs variable will be bound to the absolute path of any nixpkgs file found in the Nix search path. Similarly, a default value for helloSrc needs to be provided. Thus, assuming a checkout of Nixpkgs is available under $HOME/src/nixpkgs, the tarball jobset can now be evaluated by running: $ nix-build -I ~/src release.nix -A tarball Similarly, the build jobset can be evaluated: $ nix-build -I ~/src release.nix -A build The build job reuses the result of the tarball job, rebuilding it only if it needs to.
Adding More Jobs illustrates how to write the most basic jobs, tarball and build. In practice, much more can be done by using features readily provided by Nixpkgs or by creating new jobs as customizations of existing jobs. For instance, test coverage report for projects compiled with GCC can be automatically generated using the coverageAnalysis function provided by Nixpkgs instead of nixBuild. Back to our GNU Hello example, we can define a coverage job that produces an HTML code coverage report directly readable from the corresponding Hydra build page: coverage = { tarball ? jobs.tarball {} , system ? builtins.currentSystem }: let pkgs = import nixpkgs { inherit system; }; in pkgs.releaseTools.coverageAnalysis { name = "hello" ; src = tarball; configureFlags = [ "--disable-silent-rules" ]; }; As can be seen, the only difference compared to build is the use of coverageAnalysis. Nixpkgs provides many more build tools, including the ability to run build in virtual machines, which can themselves run another GNU/Linux distribution, which allows for the creation of packages for these distributions. Please see the pkgs/build-support/release directory of Nixpkgs for more. The NixOS manual also contains information about whole-system testing in virtual machine. Now, assume we want to build Hello with an old version of GCC, and with different configure flags. A new build_exotic job can be written that simply overrides the relevant arguments passed to nixBuild: build_exotic = { tarball ? jobs.tarball {} , system ? builtins.currentSystem }: let pkgs = import nixpkgs { inherit system; }; build = jobs.build { inherit tarball system; }; in pkgs.lib.overrideDerivation build (attrs: { buildInputs = [ pkgs.gcc33 ]; preConfigure = "gcc --version"; configureFlags = attrs.configureFlags ++ [ "--disable-nls" ]; }); The build_exotic job reuses build and overrides some of its arguments: it adds a dependency on GCC 3.3, a pre-configure phase that runs gcc --version, and adds the --disable-nls configure flags. This customization mechanism is very powerful. For instance, it can be used to change the way Hello and all its dependencies–including the C library and compiler used to build it–are built. See the Nixpkgs manual for more.