2. Build profiles and features
Two more ways to stop writing flags by hand:
- a build profile is a named set of flags FoBiS knows for each compiler (
debug,release,asan,coverage): the same mode works with gfortran, ifx or nvfortran; - a feature is a named, optional piece of configuration (here a preprocessor define) that a mode or the command line switches on.
$ fobis build --list-profiles | grep -E "compiler|----|gnu"
compiler profile cflags
-------- ------- ------
gnu asan -O1 -g -fsanitize=address,undefined -fno-omit-frame-pointer [link: -fsanitize=address,undefined] [C: -O1 -g -fsanitize=address,undefined -fno-omit-frame-pointer]
gnu coverage -O0 -g --coverage [link: --coverage] [C: -O0 -g --coverage]
gnu debug -O0 -g -fcheck=all -fbacktrace -ffpe-trap=invalid,zero,overflow -Wall -Wextra [C: -O0 -g -Wall -Wextra]
gnu release -O3 -funroll-loops [C: -O3 -funroll-loops]quad's Simpson rule needs an even number of intervals. With an odd one it returns a wrong value without a word; a check costs a test per call, so it becomes a feature, checks, compiled in only when asked:
#ifdef QUAD_CHECKS
if (mod(n, 2) /= 0) error stop 'simpson: the number of intervals must be even'
#endif(The .F90 extension tells the compiler to run the preprocessor.) The fobos declares the feature, gives the debug mode the debug profile and the feature, the release mode the release profile:
[project]
name = quad
version = 0.1.0
authors = Ada Fortran
[modes]
modes = debug release static shared coverage
[features]
checks = -DQUAD_CHECKS
[common-variables]
$PROGRAM = src/integrate.F90
$LIBRARY = src/quad_rules.F90
$OPT = -O2
[template-gnu]
compiler = gnu
src = ./src/
cflags_heritage = True
[template-library]
template = template-gnu
target = $LIBRARY
track_build = True
[debug]
help = Checks on, no optimisation
template = template-gnu
build_profile = debug
features = checks
cflags = -c
src = ./src/ ./test/
build_dir = ./build/debug/
target = $PROGRAM
[release]
help = Optimised
template = template-gnu
build_profile = release
cflags = -c
build_dir = ./build/release/
target = $PROGRAM
[static]
help = The library, static
template = template-library
cflags = -c $OPT
build_dir = ./build/static/
mklib = static
output = libquad.a
[shared]
help = The library, shared
template = template-library
cflags = -c $OPT -fPIC
build_dir = ./build/shared/
mklib = shared
output = libquad.so
[coverage]
help = Instrumented for coverage
template = template-gnu
cflags = -c -O0 -g
coverage = True
src = ./src/ ./test/
build_dir = ./build/coverage/
target = $PROGRAM
[dependencies]
penf = https://github.com/szaghi/PENF :: tag=v2.0.1build_profileprepends the profile's flags to the mode'scflags; the mode's own flags come after and win.features = checksactivates the feature in the mode;--featureson the command line adds or removes features.cflags_heritage = Truerecords the flags used in the build directory: when they change, everything is recompiled. Without it FoBiS compares only file times, and objects compiled with the old flags would stay.
A program that calls Simpson's rule with 3 intervals, in test/:
!< Simpson's rule with an odd number of intervals: wrong without a word, unless the checks are built in.
program odd_intervals
!< Simpson's rule with an odd number of intervals: wrong without a word, unless the checks are built in.
use quad_rules, only : R8P, simpson
use polynomials, only : cubic
implicit none
print '(A, F10.6)', 'integral of x**3 on [0, 2] (exact 4): ', simpson(cubic, 0._R8P, 2._R8P, 3)
endprogram odd_intervals$ fobis build --mode debug --target test/odd_intervals.F90 --output odd
Active features: checks
Builder options
Directories
Root of source files directory: "src test .fobis_deps/penf"
Building directory: "build/debug"
Compiled-objects .o directory: "build/debug/obj"
Compiled-objects .mod directory: "build/debug/mod"
Compiler options
Vendor: "gnu"
Compiler command: "gfortran"
Module directory switch: "-J"
Compiling flags: "-O0 -g -fcheck=all -fbacktrace -ffpe-trap=invalid,zero,overflow -Wall -Wextra -c -DQUAD_CHECKS"
Linking flags: ""
Preprocessing flags: ""
Coverage: False
Profile: False
Archiver: ar -rcs
Ranlib: ranlib
Preprocessor used: None
Preprocessor args:
Preprocessor output directory: None
Preprocessor extensions processed: []
Building test/odd_intervals.F90
Compiling src/quad_rules.F90 serially
Compiling test/polynomials.F90 serially
Compiling test/odd_intervals.F90 serially
Linking build/debug/odd
Target test/odd_intervals.F90 has been successfully builtThe flags are the profile's, then -c, then the feature's define. The check stops the program:
$ ./build/debug/odd
ERROR STOP simpson: the number of intervals must be even
Error termination. Backtrace:
#0 0x70f618428d14 in ???
#1 0x70f618429ab1 in ???
#2 0x70f61842b1c8 in ???
#3 0x6343151d0319 in __quad_rules_MOD_simpson
at src/quad_rules.F90:58
#4 0x6343151d0704 in odd_intervals
at test/odd_intervals.F90:8
#5 0x6343151d0786 in main
at test/odd_intervals.F90:4
[exit status 1]The same build without the feature (--features -checks removes it): the flags changed, so everything is recompiled, and the program prints a wrong integral without complaint:
$ fobis build --mode debug --features -checks --target test/odd_intervals.F90 --output odd --quiet && ./build/debug/odd
The present cflags are different from the heritages one: forcing to (re-)compile all
Building test/odd_intervals.F90
Compiling src/quad_rules.F90 serially
Compiling test/polynomials.F90 serially
Compiling test/odd_intervals.F90 serially
Linking build/debug/odd
Target test/odd_intervals.F90 has been successfully built
integral of x**3 on [0, 2] (exact 4): 3.094650The release mode cannot build that program at all: its sources are src/ only.
$ fobis build --mode release --target test/odd_intervals.F90 --output odd --quiet
Error: the target "test/odd_intervals.F90" is not among the sources of this build (src: src .fobis_deps/penf): add its directory to the mode's src
[exit status 1](The program is removed after this chapter: a test that is meant to fail does not belong in test/.)
What you learned
build_profile, --list-profiles, [features] and --features (-name to remove one), cflags_heritage. Reference: build profiles, feature flags.
Next: 3. OpenMP and MPI.