Skip to content

10. Several programs and a library for others ​

So far each mode built one program. This chapter builds all of quad's programs in one call, each with its own flags, describes its library so that any build system can link it, and gives editors the exact commands that compile each file.

Several programs, one build ​

[target.NAME] sections name the programs of a build; a key in a section replaces the mode's. They live in a fobos of their own, programs.fobos, because a fobos with target sections cannot have modes that name a target, and every mode of quad's fobos does:

console
$ cat programs.fobos
[modes]
modes = programs

[programs]
help      = Every program of quad, each with its own flags
compiler  = gnu
cflags    = -c -O2
src       = ./src/
build_dir = ./build/programs/

[target.integrate]
source = src/integrate.F90

[target.sweep]
source = src/sweep.F90
openmp = True
console
$ fobis build -f programs.fobos --quiet

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/programs/integrate
Target src/integrate.F90 has been successfully built

Building src/sweep.F90
Compiling src/sweep.F90 serially
Linking build/programs/sweep
Target src/sweep.F90 has been successfully built

sweep alone was built with OpenMP:

console
$ OMP_NUM_THREADS=2 ./build/programs/sweep | tail -n 2
  2048        3.9218E-07        5.7732E-14
  4096        9.8046E-08        3.9968E-15

--target-filter builds some of the targets only. The targets share the mode's objects, so nothing is compiled again:

console
$ fobis build -f programs.fobos --target-filter sweep --quiet

Building src/sweep.F90
Nothing to compile, all objects are up-to-date
Linking build/programs/sweep
Target src/sweep.F90 has been successfully built

pkgconfig = True in a library mode writes a pkg-config file next to the library. Its version is the [project] version:

ini
[static]
help      = The library, static
template  = template-library
cflags    = -c $OPT
build_dir = ./build/static/
mklib     = static
output    = libquad.a
pkgconfig = True
console
$ fobis build --mode static --quiet && cat build/static/quad.pc

Building src/quad_rules.F90
Nothing to compile, all objects are up-to-date
Linking build/static/libquad.a
Target src/quad_rules.F90 has been successfully built
Track building of src/quad_rules.F90
pkg-config file build/static/quad.pc
# Generated by FoBiS.py v3.15.0
prefix=~/quad/build/static
libdir=${prefix}
includedir=${prefix}/mod

Name: quad
Description: 
Version: 0.1.0
Libs: -L${libdir} -lquad
Libs.private:
Cflags: -I${includedir}

A program outside the project, built by hand with gfortran, finds the module files and the library through it:

fortran
module curves
!< An integrand of the consumer's own.
use quad_rules, only : R8P
implicit none
contains
   pure function parabola(x) result(y)
   real(R8P), intent(in) :: x
   real(R8P)             :: y
   y = 3._R8P * x * x
   endfunction parabola
end module curves

program use_quad
!< A program outside the project, linked to quad through pkg-config.
use quad_rules, only : R8P, simpson
use curves,     only : parabola
implicit none
print '(F8.5)', simpson(parabola, 0._R8P, 1._R8P, 2)
end program use_quad
console
$ cd ~ && gfortran use_quad.f90 $(PKG_CONFIG_PATH=quad/build/static pkg-config --cflags --libs quad) -o use_quad && ./use_quad
 1.00000

The same file serves CMake (pkg_check_modules) and make (pkg-config --cflags --libs quad). fobis install writes one into the prefix it installs to, with the installed paths.

The compile commands, for editors ​

Language servers (fortls, clangd for the C files) need each file's compile command. --compile-commands writes them into the build directory and links compile_commands.json at the project root:

console
$ ls -l compile_commands.json | sed "s/.* compile_commands/compile_commands/"
compile_commands.json -> build/debug/compile_commands.json
console
$ grep -o "\"file\": \"[^\"]*/quad/\(src\|test\)/[^\"]*\"" compile_commands.json
"file": "~/quad/src/integrands.F90"
"file": "~/quad/src/integrate.F90"
"file": "~/quad/src/integrate_mpi.F90"
"file": "~/quad/src/quad_rules.F90"
"file": "~/quad/src/sweep.F90"
"file": "~/quad/test/polynomials.F90"
"file": "~/quad/test/test_exactness.F90"
"file": "~/quad/test/test_order.F90"

The database has an entry for every file of the mode's sources, compiled or not (the fetched PENF's too), with the mode's flags and macros. Build in another mode to point the editor at that mode's flags.

What you learned

[target.NAME] sections, --target-filter, -f, pkgconfig = True, linking through pkg-config, --compile-commands. Reference: one program out of many, pkg-config files, compile commands.

This is the end of the second track. The third leaves quad for a while: a family of projects that depend on each other, managed together.