9. One fobos, many machines
quad is built on a laptop and on a cluster. The two differ in a few values (here, the processor the code is tuned for), and a project may be built with other compilers too. Copying the modes for each machine would double the fobos; this chapter keeps one set of modes and moves what differs into values chosen at build time.
Values chosen by machine: varsets
A varset is a named set of $variables. The machines get their own file, included by the fobos, which also lists an optional file of the developer's own:
[include]
paths = machines.fobos
?fobos.local$ cat machines.fobos
[varsets]
default = laptop
[varset:laptop]
$TUNE = -mtune=native
[varset:cluster]
$TUNE = -mtune=znver3The release mode uses $TUNE, and adds a flag only when the compiler is gfortran:
[release]
help = Optimised
template = template-gnu
build_profile = release
cflags = -c $TUNE
cflags.gnu = -fimplicit-none
cflags.intel = -warn all
post_build = smoke
build_dir = ./build/release/
target = $PROGRAMfobis introspect shows the varsets and the flags they give:
$ fobis introspect --varsets
{
"varsets": {
"default": [
"laptop"
],
"varsets": {
"laptop": {
"$TUNE": "-mtune=native"
},
"cluster": {
"$TUNE": "-mtune=znver3"
}
}
}
}$ fobis introspect --buildoptions --mode release
{
"buildoptions": {
"mode": "release",
"build_dir": "./build/release/",
"obj_dir": "./obj/",
"mod_dir": "./mod/",
"mklib": "",
"jobs": 1,
"qualified_keys": [
{
"key": "cflags.gnu",
"kind": "compiler",
"value": "-fimplicit-none",
"applied": true,
"how": "appended",
"result": "-O3 -funroll-loops -c -mtune=native -fimplicit-none"
},
{
"key": "cflags.intel",
"kind": "compiler",
"value": "-warn all",
"applied": false
}
]
}
}--varset cluster selects the other one:
$ fobis introspect --buildoptions --mode release --varset cluster
{
"buildoptions": {
"mode": "release",
"build_dir": "./build/release/",
"obj_dir": "./obj/",
"mod_dir": "./mod/",
"mklib": "",
"jobs": 1,
"qualified_keys": [
{
"key": "cflags.gnu",
"kind": "compiler",
"value": "-fimplicit-none",
"applied": true,
"how": "appended",
"result": "-O3 -funroll-loops -c -mtune=znver3 -fimplicit-none"
},
{
"key": "cflags.intel",
"kind": "compiler",
"value": "-warn all",
"applied": false
}
]
}
}qualified_keys reports what cflags.gnu and cflags.intel did: the first was appended because the mode's compiler is gfortran, the second was not applied. A key qualified by a system (cflags.linux, ext_libs.windows) works the same way.
Build for the cluster
The first build compiles with the default varset, laptop. cflags_heritage = True (from the template) records the flags, so building for the cluster compiles everything again:
$ fobis build --mode release --quiet --force-compile
Building src/integrate.F90
Compiling .fobis_deps/penf/src/lib/penf_global_parameters_variables.F90 serially
Compiling .fobis_deps/penf/src/lib/penf_b_size.F90 serially
Compiling .fobis_deps/penf/src/lib/penf_stringify.F90 serially
Compiling src/quad_rules.F90 .fobis_deps/penf/src/lib/penf_allocatable_memory.F90 serially
Compiling src/integrands.F90 .fobis_deps/penf/src/lib/penf.F90 serially
Compiling src/integrate.F90 serially
Linking build/release/integrate
Target src/integrate.F90 has been successfully built
Executing rule "smoke"
Command => ./build/release/integrate | tail -n 1
Simpson, 64 intervals: 2.0000000645300013$ fobis build --mode release --varset cluster --quiet
The present cflags are different from the heritages one: forcing to (re-)compile all
Building src/integrate.F90
Compiling .fobis_deps/penf/src/lib/penf_global_parameters_variables.F90 serially
Compiling .fobis_deps/penf/src/lib/penf_b_size.F90 serially
Compiling .fobis_deps/penf/src/lib/penf_stringify.F90 serially
Compiling src/quad_rules.F90 .fobis_deps/penf/src/lib/penf_allocatable_memory.F90 serially
Compiling src/integrands.F90 .fobis_deps/penf/src/lib/penf.F90 serially
Compiling src/integrate.F90 serially
Linking build/release/integrate
Target src/integrate.F90 has been successfully built
Executing rule "smoke"
Command => ./build/release/integrate | tail -n 1
Simpson, 64 intervals: 2.0000000645300013A varset that does not exist stops the build and lists the defined ones:
$ fobis build --mode release --varset nowhere
Error: varset 'nowhere' is not defined.
Available varsets: cluster, laptop
[exit status 1]A developer's own values
?fobos.local is optional: without the file nothing happens. A developer who wants other values writes it, and it wins over machines.fobos because it comes later in paths. It is ignored by git, so it never reaches the repository:
$ cat fobos.local && git status --short
[varset:laptop]
$TUNE = -mtune=generic
M .gitignore
M fobos
?? machines.fobos$ fobis introspect --buildoptions --mode release
{
"buildoptions": {
"mode": "release",
"build_dir": "./build/release/",
"obj_dir": "./obj/",
"mod_dir": "./mod/",
"mklib": "",
"jobs": 1,
"qualified_keys": [
{
"key": "cflags.gnu",
"kind": "compiler",
"value": "-fimplicit-none",
"applied": true,
"how": "appended",
"result": "-O3 -funroll-loops -c -mtune=generic -fimplicit-none"
},
{
"key": "cflags.intel",
"kind": "compiler",
"value": "-warn all",
"applied": false
}
]
}
}What you learned
[varset:NAME], [varsets] default, --varset, keys qualified by a compiler (cflags.gnu), [include] paths with an optional ?file, fobis introspect --varsets and --buildoptions. Reference: varsets, qualified keys, includes.