More complex configurations with Nickel¶
nitrile.ncl
is an alternative to nitrile.yml
that allows to
prevent duplication within the definition of your package. This approach makes
use of the programming language Nickel to generate
the package configuration.
When using this approach, all that is necessary is to create a nitrile.ncl
file. Nitrile will call Nickel under the hood, so a nitrile.yml
file is not
necessary (and will be ignored if it exists).
Setting up¶
To use the nitrile.ncl
approach,
install Nickel and include it
in your system path. It is also possible to provide a custom executable, or use
Docker, through a global setting.
Nickel is also included within the
cleanlang/nitrile Docker image.
The result of nitrile.ncl
should be a valid
package configuration. For details on Nickel syntax and
features, please refer to the
Nickel User Manual.
Info
To check what kind of configuration the nitrile.ncl
file would produce, run
nickel export nitrile.ncl --format yaml
or use
the Nickel Playground.
Example to avoid duplication¶
Consider the following test specification in nitrile.yml
:
tests:
unit:
script:
- clm: {src: [tests], main: test1, target: tests/test1}
- clm: {src: [tests], main: test2, target: tests/test2}
- clm: {src: [tests], main: test3, target: tests/test3}
- test-runner:
tests:
- ./tests/test1
- ./tests/test2
- ./tests/test3
In a Nickel configuration, this could be simplified as:
let
unit_tests = fun cases => {
script =
std.array.map (fun c => {clm = {src = ["tests"], main = c, target = "tests/" ++ c}}) cases @
[{ test-runner.tests = std.array.map ((++) "tests/") cases }]
}
in
{
# rest of the package configuration...,
tests.unit = unit_tests ["test1", "test2", "test3"]
}
Example with command line options¶
Nickel specifications can also be used to customize a project’s configuration
using command line options. Suppose one wants to be able to build their
application in a “develop” configuration with
stack tracing enabled, and in a “production”
configuration without stack tracing. Using a YAML specification, the only
option is to define two separate build targets, and require the user to specify
which is used with --only
:
build:
production:
script:
- clm:
main: app
target: bin/app
develop:
script:
- clm:
main: app
target: bin/app
profiling: StackTracing
With Nickel it is possible to define a single build target in which certain
values can be customized on the command line using
--define
. Variables defined
with --define=VARIABLE[:VALUE]
can be accessed in Nickel as
nitrile.options.VARIABLE
:
{
nitrile | not_exported = {
options = {
develop | Bool | default = false
}
},
# rest of the package configuration...,
build.app = {
script = [
{ clm = {
main = "app",
target = "bin/app",
profiling = if nitrile.options.develop then "StackTracing" else null
} }
]
}
}
Nitrile can now be called with --define=develop:true
to override the default
setting.
Info
The root field nitrile
in the Nickel configuration needs to be marked as
not_exported
.
Multiple packages¶
If you need to define multiple packages, let your Nickel configuration return an array of configurations.