Skip to content

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.
console
$ 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:

fortran
#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:

ini
[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.1
  • build_profile prepends the profile's flags to the mode's cflags; the mode's own flags come after and win.
  • features = checks activates the feature in the mode; --features on the command line adds or removes features.
  • cflags_heritage = True records 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/:

fortran
!< 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
console
$ 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 built

The flags are the profile's, then -c, then the feature's define. The check stops the program:

console
$ ./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:

console
$ 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.094650

The release mode cannot build that program at all: its sources are src/ only.

console
$ 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.