NOTE: The vernix tool was intended to provide management of specific package versions and support for building both locally and under hydra. It achieved this goal for many common uses, but it had trouble supporting specific modifications and adjustments to packages: vernix used its own input representation that was translated to nix, and so each of these modifications and adjustments needed to be replicated in the vernix input language as well. It became apparent that a small and simple representation of nix build configurations was ill-conceived and rather than continuing to create a parallel representation, a more native representation would be a better approach. To this end, the devnix (https://github.com/kquick/devnix) module is the modern replacement, and subsequently the briareus tool (https://github.com/kquick/briareus) for generating build configurations enhances the devnix usage. No further development of vernix is planned.
This is a tool to generate nix expressions for packages with specific versions.
- Download the vernix file and make sure the executable bit is set.
- This script is designed to use nix-shell, which assumes that you need have nix installed. This is judged to be a safe assumption, since the output and purpose of this tool is creating nix specifications.
- Create a
FILE.vx2
(or apackage_spec
file) describing the override packages you need. Use$ vernix --help
to get information on how to create the input package specification. The file is in Python syntax. - Run
$ vernix
to get a...-project.nix
file. - Follow the instructions in the comments at the end of that project.nix file.
- Optionally use additional arguments (e.g.
--fast
).
Note that because vernix is preparing elements for the nix build tools, it must be run in an environment where those tools are available.
The vernix tool can also be used to help configure the Hydra continuous build system. For more information, see HydraUsage.org.
An example package spec for building the Matterhorn client for Mattermost. This client is written in Haskell. The client itself is loaded from github and there are some specific Haskell package version overrides.
The default project.nix file will either be frozen to the versions
available at the time vernix
created it (by default or if --static
is used), or it will automatically check the source locations each
time a nix evaluation is performed (e.g. nix-shell
or nix-build
)
when --dynamic
is used. and therefore update to any recent changes
for packages not pinned to a specific version.
It is only necessary to re-run vernix
if the package_spec
input
changes or to update for new upstream nixpkgs
changes.
Why and When you might use vernix
The nixpkgs set of tools and package descriptions are a great way to do controlled, reproducable development and product maintenance, but can be somewhat difficult to work with when developing a project, especially one made up of lots of dependent repositories (e.g. git submodules) and written in a language with its own package manager.
At this stage (2018), nix has pretty good integration with various package managers which allows it to manage individual packages.
What the nixpkg setup has historically not been good at is tracking version changes in a package. A particular package references its dependencies by name only, with no version tag. Only when there is an incompatibility with multiple necessary clients is there a specific version of a package created, and the version is embedded in the package name.
It should be possible to develop and/or install something with an explicit set of versioned dependencies. The versioning of the dependencies may be controlled by a separate tool (cabal, cargo, pip, etc.), but it should be possible for nix to present the specific versions of those dependencies for the build.
The primary use case for this is development, when a nix-shell is used to create the development environment. It may be useful however to have this enabled for normal installations and even production packages: as the number of packages grows, it becomes increasingly likely that user-requested installs will have conflicting versions of package requirements that do not lend themselves easily to version-encoded name special cases.
As another side effect, it should become easier to run different versions of the target language environment for testing (e.g. GHC 7.10 v.s. 8.0.2 v.s. 8.2.2, or rust stable v.s. nightly).
This is a nice way of creating specific sets of overlays and managing them separately. Unfortunately, they are all applied for a particular nix operation, so different packages with conflicting version requirements will still have problems.
This ultimately is not a good solution if you are looking for per-project variations. A better solution is one in which the dependencies tend toward the default installed versions, but which can be explicitly overloaded, but only for building that package and its dependency set.
Build a specific foo-project.nix file which contains explicit nix specifications that are only applied when running that file. All nix-shell/nix-env operations will utilize that file to obtain the configuration.
Create a tool to build that file as needed: vernix
.
The current primary language environment target is Haskell/cabal, although other language should be possible to support.
- Efficient Builds
- means that build artifacts from previous builds can be safely re-used in new builds, and that builds only generate the minimal set of operations needed relative to the previous builds.
- Shareable
- means that the build output can be re-used by other projects, and other people on other machines.
: \ Tool–> | vernix | cabal | cabal-new | stack | styx | cabal2nix | nix | git |
v Feature \ | cabal 2 | packages | submodules | |||||
---|---|---|---|---|---|---|---|---|
Local Build | * | * | * | * | * | * | * | * |
Multi-package Local Build | * | * | * | * | * | |||
Git references | * | * | * | * | ||||
Hackage references | * | * | * | * | ||||
Explicit versions | * | * | * | * | ||||
Non-Haskell packages | * | * | * | |||||
Compiler variants | * | * | * | * | ||||
Package Caches | global | directory | user | directory | global | global | ||
CB/CI integration | Hydra | |||||||
Efficient Builds | * | * | ||||||
Shareable | * | * | * |
This is a non-standard tool, and Haskell-only.
Similar to vernix:
- Does not provide Hydra output
- The input file is yaml. This may be more “declarative” than vernix’s Python input, but also requires more duplication.
- Less per-project control (e.g. per-project additional dependencies, build flag control such as noCheck, etc.).
Based on the nix principles, and works fairly well for haskell packages, but does not extend to OS-level packages needed (e.g. zip).
Also, this tool is still under development and is incomplete at this time.
Good to translate cabal files to nix files, but all dependencies are specified without versioning, so there must be nix mappings to any specific versions required.
The haskell package infrastructure is missing a couple of key elements (e.g. cabal2nix subpath) and doesn’t handle sub-versions too well. It’s also not convenient when working with packages that are not part of the standard nixpkgs distribution (either local packages or packages newer than what has been incorporated into the distribution).
Not useable outside of git. Very complicated, with extra management and setup/checkout needed. Doesn’t work for non-git modules, and only useful for building from source, not for specifying specific external packaging versioning.