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:
$ 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$ 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 builtsweep alone was built with OpenMP:
$ 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:
$ 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 builtA library any build system can link
pkgconfig = True in a library mode writes a pkg-config file next to the library. Its version is the [project] version:
[static]
help = The library, static
template = template-library
cflags = -c $OPT
build_dir = ./build/static/
mklib = static
output = libquad.a
pkgconfig = True$ 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:
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$ cd ~ && gfortran use_quad.f90 $(PKG_CONFIG_PATH=quad/build/static pkg-config --cflags --libs quad) -o use_quad && ./use_quad
1.00000The 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:
$ ls -l compile_commands.json | sed "s/.* compile_commands/compile_commands/"
compile_commands.json -> build/debug/compile_commands.json$ 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.