Working with Dependent Projects
Posted on 2018-12-13
NOTE: Users will need at least version 3.0 build 2898 for this example
With the release of Simply Fortran version 3.0, the development environment now supports the concept of dependent projects. A parent project can now include a dependent project in its Project Outline panel, and building the parent project will build the dependent project first without necessarily having the dependent project open in Simply Fortran at all. This paradigm is useful if users have, for example, an executable project that relies on one or more libraries that are also built using Simply Fortran. In version 3.0, building the executable project can trigger building the libraries automatically.
To demonstrate this feature, consider a simple project where we need to generate some lucky numbers. Conceptually, we might want a few different user interfaces, but the underlying computational code wouldn't rely on the user-facing program. We'll start with a simple, single-file library that includes a random number generator:
C Initialize our lucky number system subroutine init_lucky_numbers() implicit none call random_seed() end subroutine init_lucky_numbers C Generate an array of random numbers between the two C specified values subroutine lucky_numbers(values, lowest, highest) implicit none integer, dimension(:), intent(inout)::values integer, intent(in)::lowest, highest integer::i, full_range real::random_value C Error checking if(highest <= lowest) then values = lowest return end if full_range = highest - lowest C Loop through our array do i=lbound(values, 1), ubound(values, 1) call random_number(random_value) C Scale the value to be between our numbers of interest random_value = random_value*real(full_range) + . real(lowest) C Scale to the nearest integer and store it values(i) = nint(random_value) end do end subroutine lucky_numbers
We've written this code in fixed-format Fortran, though it uses a substantial amount of modern Fortran intrinsic procedures and syntax. The file contains two subroutines. The first simply initializes the random number generator, and the second will fill the array values with random integers between lowest and highest. There is some math involved in converting the uniform random numbers from the intrinsic random_number, but it's relatively straightforward and completely portable. We can place this file in a static library project by itself called libnumbers.prj with a target libnumbers.a.
Next, we'll need to write an interface to this library. To be cross-platform, a text interface is the simplest route. Since our library is external, we'll also need interface blocks for the two functions. Here's a simple example program:
program main implicit none integer, parameter::lowest = 1 integer, parameter::highest = 69 integer, parameter::length = 5 integer, dimension(length)::values character::cmd integer::i interface subroutine init_lucky_numbers end subroutine init_lucky_numbers end interface interface subroutine lucky_numbers(v, l, h) integer, dimension(:), intent(inout)::v integer, intent(in)::l, h end subroutine lucky_numbers end interface call init_lucky_numbers() write(*, '(A)', ADVANCE='NO') "Press [ENTER] to generate or [Q] and [ENTER] to quit: " read(*,'(A1)') cmd do while(cmd .NE. 'Q' .AND. cmd .NE. 'q') call lucky_numbers(values, lowest, highest) write(*, '(2X,5(I2,4X))') (values(i),i=1,length) write(*, '(A)', ADVANCE='NO') "Press [ENTER] to generate or [Q] and [ENTER] to quit: " read(*,'(A1)') cmd end do write (*,*) " " end program main
Normally in the past, we'd build the original library separately and add a flag to this parent project to link to said library. With version 3.0 of Simply Fortran, we can directly add the library project to our parent project. After clicking "Add File(s)..." in the Project menu, navigate and select the project file itself. Once added, our parent project should look like this:
From our parent project, we can now build everything, including our dependent project. Clicking "Build Project" from the Build menu will produce the following in our Build Status tab:
Notice in the Build Status tab that the libnumbers project was also built simply by building our parent project. The resulting executable works exactly as one expects.
We can also build a different front end using the same library for Windows users with AppGraphics:
This example is, of course, somewhat trivial. It does, however, illustrate the ease with which project dependencies can be used. While we've shown a static library as a dependent project, the same procedure works with dynamic libraries or even executable projects. In the case of an executable, the dependent executable is simply built first (as opposed to linking to the parent project).
Below is a link to an archive containing our three projects: two parent projects and one dependent library project. The AppGraphics project only works on the Windows platform.
- Example Lucky Numbers Projects: LuckyNumbers.zip
If you have any troubles with dependent projects or have any suggestions for additional features, please see our Support page for documentation and contact information. We're always happy to help!