As shown in Chapter 7, Structuring Projects, we will structure our project as a tree. Each subdirectory has a CMakeLists.txt file with instructions pertaining to that directory. This allows us to confine as much information as possible within the leaf directories as in this example:
.
├── CMakeLists.txt
└── src
├── bt-randomgen-example.f90
├── CMakeLists.txt
├── interfaces
│ ├── CMakeLists.txt
│ ├── interface_backtrace.f90
│ ├── interface_randomgen.f90
│ └── randomgen.c
└── utils
├── CMakeLists.txt
└── util_strings.f90
In our case, we have a src subdirectory containing the sources, including bt-randomgen-example.f90, our executable. Two further subdirectories, interfaces and utils, contain more source code that will be compiled into libraries.
The source code in the interfaces subdirectory shows how to wrap the backtrace C system library. For example, the interface_backtrace.f90 contains:
module interface_backtrace
implicit none
interface
function backtrace(buffer, size) result(bt) bind(C, name="backtrace")
use, intrinsic :: iso_c_binding, only: c_int, c_ptr
type(c_ptr) :: buffer
integer(c_int), value :: size
integer(c_int) :: bt
end function
subroutine backtrace_symbols_fd(buffer, size, fd) bind(C, name="backtrace_symbols_fd")
use, intrinsic :: iso_c_binding, only: c_int, c_ptr
type(c_ptr) :: buffer
integer(c_int), value :: size, fd
end subroutine
end interface
end module
The above example shows the use of the following:
- The intrinsic iso_c_binding module, which ensures interoperability of Fortran and C types and functions.
- The interface declaration, which binds the functions to symbols in a separate library.
- The bind(C) attribute, which fixes name-mangling of the declared functions.
This subdirectory contains two more source files:
- randomgen.c, which is a C source file that exposes a function, using the C standard rand function, to generate random integers within an interval.
- interface_randomgen.f90, which wraps the C functions for use within a Fortran executable.