Skip to content

4. A project that depends on quad ​

In chapter 3 of First steps a separate project used quad once installed. While both are being developed, installing after every change is a chore; dependon builds the library first, every time, and wires its module files and its archive in:

ini
[default]
compiler = gnu
cflags   = -c -O2
src      = ./src/
target   = src/area.F90
dependon = ../quad/fobos:static((direct))
fortran
!< The area under x**2 on [0, 1], with the installed quad library.
program area
!< The area under x**2 on [0, 1], with the installed quad library.
use quad_rules, only : R8P, simpson
use curves,     only : parabola
implicit none

print '(A, F18.15)', 'area = ', simpson(parabola, 0._R8P, 1._R8P, 2)
endprogram area
fortran
!< The curves whose areas we want.
module curves
!< The curves whose areas we want.
use quad_rules, only : R8P
implicit none
private
public :: parabola

contains
   pure function parabola(x) result(y)
   !< x**2.
   real(R8P), intent(in) :: x !< Abscissa.
   real(R8P)             :: y !< x**2.

   y = x * x
   endfunction parabola
endmodule curves

dependon = ../quad/fobos:static((direct)) reads: the fobos at that path (relative to the directory fobis runs in, here the project's root), its static mode, and link the library by its full path (((indirect)) links it by name, with -L and -l).

console
$ cd ~/area && fobis build
Building dependency fobos into ../quad with mode static
Builder options
  Directories
    Root of source files directory: "src .fobis_deps/penf"
    Building directory: "build/static"
    Compiled-objects .o   directory: "build/static/obj"
    Compiled-objects .mod directory: "build/static/mod"
  Compiler options
    Vendor: "gnu"
    Compiler command: "gfortran"
    Module directory switch: "-J"
    Compiling flags: "-c -O2"
    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 src/quad_rules.F90
Compiling src/quad_rules.F90 serially
Linking build/static/libquad.a
Target src/quad_rules.F90 has been successfully built
Track building of src/quad_rules.F90

The following auxiliary paths have been added
Include files search paths (include):
- ../quad/build/static/mod
Libraries search paths (lib_dir):
Libraries paths:
- (libs) ../quad/build/static/libquad.a
Builder options
  Directories
    Root of source files directory: "src"
    Building directory: "."
    Compiled-objects .o   directory: "obj"
    Compiled-objects .mod directory: "mod"
  Included paths: ../quad/build/static/mod 
  Linked libraries with full path: ../quad/build/static/libquad.a 
  Compiler options
    Vendor: "gnu"
    Compiler command: "gfortran"
    Module directory switch: "-J"
    Compiling flags: "-c -O2"
    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 src/area.F90
Compiling src/curves.F90 serially
Compiling src/area.F90 serially
Linking ./area
Target src/area.F90 has been successfully built

FoBiS built quad's static library in its own directory, then added its module directory to the include path and the archive to the libraries. When nothing changed, the library build is a no-op:

console
$ cd ~/area && fobis build --quiet && ./area
Building dependency fobos into ../quad with mode static

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

The following auxiliary paths have been added
Include files search paths (include):
- ../quad/build/static/mod
Libraries search paths (lib_dir):
Libraries paths:
- (libs) ../quad/build/static/libquad.a

Building src/area.F90
Nothing to compile, all objects are up-to-date
Linking ./area
Target src/area.F90 has been successfully built
area =  0.333333333333333

dependon: the dependency's library is built first, then linked

Recorded on a small demo project, not quad.

When the library changes ​

A change to the body of a procedure recompiles the library and relinks area; area's own files need not compile again:

console
$ touch src/quad_rules.F90 && cd ~/area && fobis build --quiet
Building dependency fobos into ../quad with mode static

Building src/quad_rules.F90
Compiling src/quad_rules.F90 serially
Linking build/static/libquad.a
Target src/quad_rules.F90 has been successfully built
Track building of src/quad_rules.F90

The following auxiliary paths have been added
Include files search paths (include):
- ../quad/build/static/mod
Libraries search paths (lib_dir):
Libraries paths:
- (libs) ../quad/build/static/libquad.a

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

A change to the library's interface is different: area's objects were compiled against the old one. Here a new rule, midpoint, is added to quad_rules:

fortran
public :: R8P, integrand, midpoint, trapezoid, simpson
console
$ cd ~/area && fobis build --quiet
Building dependency fobos into ../quad with mode static

Building src/quad_rules.F90
Compiling src/quad_rules.F90 serially
Linking build/static/libquad.a
Target src/quad_rules.F90 has been successfully built
Track building of src/quad_rules.F90

The following auxiliary paths have been added
Include files search paths (include):
- ../quad/build/static/mod
Libraries search paths (lib_dir):
Libraries paths:
- (libs) ../quad/build/static/libquad.a

Building src/area.F90
Compiling src/curves.F90 serially
Compiling src/area.F90 serially
Linking ./area
Target src/area.F90 has been successfully built

gfortran rewrites a module file only when the module's interface changes, so FoBiS compares the time of the .mod files of the modules a file uses from outside the project with the file's object: curves and area were recompiled.

The lighter alternative: a path dependency ​

When area only needs quad's modules, not its library, the [dependencies] section can name the directory:

ini
[dependencies]
quad = path=../quad

quad's sources are then compiled with area's, as a dependency fetched from GitHub would be (its .git, build and fetched-dependency directories skipped). Nothing is fetched or installed, and an edit in ../quad is recompiled at the next build. quad = path=../quad :: use=fobos :: mode=static builds it with its own fobos and links the library instead, which is this chapter's dependon without the link syntax. Cookbook: local directories.

What you learned

dependon = PATH:MODE((direct|indirect)): another project's library rebuilt first, its module files and archive wired in, its interface changes followed. For dependencies from GitHub, [dependencies] does the same from a clone. Reference: interdependent projects.

Next: 5. Rules.