-
Notifications
You must be signed in to change notification settings - Fork 4
Handling Multiple Compilers
An important aspect of software testing is making sure that all relevant compiler versions still work when code is changed; otherwise existing users may be locked out from future updates or bug fixes when new features only work with newer compilers. Specifically for Fortran, we also have the the different behaviors of ifort
vs. gfortran
. For example, each handles random seeds differently; if you want to seed the random number generator to fix the output results of unit tests, then the seed input files for ifort
and gfortran
are different.
Starting with revision 1.5.4, fortpy supports multiple compilers as described below.
This is an example of the new compilers.xml
file. It specifies names, keys and paths to compilers available on the local system running fortpy.
<?xml version="1.0"?>
<compilers>
<compiler path="/usr/local/bin/gfortran" key="g49" name="gfortran49"
default="true" />
<compiler path="/usr/local/bin/ifort" key="i15" name="ifort15" />
</compilers>
- path specifies the full path to the compiler executable that fortpy should use.
-
key if specified, this key will be spliced into all input/output files that have
[c]
in the filename (i.e.[c]
will be replaced by this key before copying input/output files to execution directories). Additionally, when the unit tests are run, the executing directory will be calledmodule.executable.key
for each compiler used. -
name for the
-compiler
argument ofruntests.py
. Change that argument to accept a string. If the string is*
, then run the unit tests separately for every compiler in thecompilers.xml
file. Otherwise, only run those compilers whose names match the string given. -
default if
-compiler
is run without specifying a string, this is the compiler that would be used by default. If none of the compilers in the file have this attribute, the first one listed is used.
The path to this file should be specified using the following tag, added to the global fortpy configuration file.
<compilers>~/codes/fortpy-dist/fortpy/compilers.xml</compilers>
To have fortpy test the code against all the compilers listed in compilers.xml
, runtests.py
will be executed exactly as before; the only change is that -compilers "*"
would be added as an option.
As described in the introduction, if different compilers/compiler families need different versions of input/output files, these can be specified by including the compiler key in the file name. When the input/output file is specified in the unit testing XML file, include [c]
in the file name at the location where the compiler key should be inserted. As an example, consider the following <input>
tag from a testing group:
<test identifier="random" description="Example of random seed with multiple compilers"
cases="1, 2" timed="true">
<input folder="./tests" file="randseed.[c].in.{}" rename="randseed.in" />
</test>
Now, suppose that I have the compilers as specified in the example compilers.xml
file above. Then, inside the tests
folder, I expect to find four files: randseed.g49.in.1
, randseed.g49.in.2
, randseed.i15.in.1
, and randseed.i15.in.2
. When these input files are copied to the execution directory, they will all be renamed to randseed.in
so that the code can reference only a single file name, independent of the compiler.
When the tests are run with -compilers "*"
using runtests.py
, fortpy will create three directories:
-
module.random
: a clean copy of all the dependencies and make files needed for the compilation. -
module.random.g49
: a copy ofmodule.random
which gets compiled with thegfortran
compiler. -
module.random.i15
: a copy ofmodule.random
, but compiled with ifort instead.
The unit tests are executed in each respective directory.
In addition to modifying the input file names by compiler (using the [c]
field), fortpy also supports replacing compiler families using the field [f]
. If the compiler is a gfortran
compiler version, the family key is g
; for ifort
, the family character is i
. A file name such as randseed.[f].in.{}
from the example above would become randseed.g.in.1
and randseed.i.in.1
. The replacement only takes place for file names.