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!