Wednesday 2 July 2014

The Fortran makefile dependency problem

For a project comprising of C/C++ code and header files, to simply compile once there is often no need for dependencies. Assuming that none of the header files are generated as part of the build process, it doesn't matter which order the source files are compiled in.

When developing a piece of code it is inefficient to recompile all the source files when a file has changed. Instead just the files which depend on those changes need to be recompiled. For example, when modifying a single C file only that file need be recompiled, or in the case of modifying a header file, all source files which include the header should be recompiled.

For a while standalone tools such as makedepend were used to generate these dependencies, but these have largely been superceded by the compilers themselves, commonly via a '-M' flag. This has great advantages, not least because the compiler itself knows best how to pre-process the file and which defines are internally set. A typical setup would therefore compile all files and then generate dependencies during the initial make. Subsequent makes include those dependencies and only recompiles things that have changed or are newly created, whilst of course also updating any dependencies accordingly.


There is a problem if one attempts to apply such a set-up to a Fortran project, namely F90 module files. Modules are similar to C header files, except that they themselves are source code which must be compiled before they can be used. For a small project one can of course write by hand that file A generates module M which is needed by files B and C. However, for larger projects, where modules are including other modules, which include other modules etc. this quickly becomes complicated. Some Fortran compilers (eg. gfortran) are able to generate dependencies via a '-M' option, but this is of little help since it can't be done until the relevant modules are available, a classic chicken and egg situation.

So unlike C, with Fortran the order in which source files should be compiled matters, and therefore dependencies must be generated before any compilation is done. This has unsurprisingly resulted in a whole series of tools designed to do this, sfmakedepend is the first that google turns up. In truth, many of these tools are actually more complicated than they need be since they often attempt to deal with Fortran and CPP include directives. These could be handled in the same way as C include directives, but of course it has the advantage that one does not need to generate separately module and include dependencies.

In conclusion, with Fortran one needs to generate at least module dependencies for all source files, and then include those dependencies before attempting to compile any source code.

It should be mentioned that for a Fortran project not making use of F90 module files this problem of course does not exist.

Tuesday 1 July 2014

EKOPath dependency generation bug

Most C/C++ compilers support dependency generation, often through the -M series of flags. For some reason the two version of EKOPath I've installed (5.0.1 and 5.0.5) contain a bug such that:

> pathCC -M test.cpp
psclang: error: unknown argument: '-Eonly'

The solution is to instruct the compiler to pre-process only and pass the -M option through to the preprocessor, i.e.:

> pathCC -E -Wp,-M test.cpp
test.o: test.cpp test.h

Wednesday 25 June 2014

OSX command line user admin

Setting up and modifying user accounts via the command line on OSX is a bit of pain. The supplied tools to do it require one to not only set reasonable things, such as login name, but to also choose a unique id, assign a primary group etc., things that the graphical way of creating users automatically populate with sensible defaults.

Examples of when one might need to do this are: when a machine is only accessible via ssh; when a sysadmin wants a script to run on multiple machines to setup a series of user accounts.

On Linux there are utilities such as useradd which has many options, but crucially has sensible defaults such that in practice only a few need be specified to create a new account, eg.:

useradd -m -c 'Joe Bloggs' joe

Inspired by personal experience of attempting to create a new user account on an OSX machine via ssh, I wrote versions of useradd etc. for OSX, which are available here. Of course I only implemented the features that I needed at the time... but will perhaps make them more complete in the future.

Wednesday 18 June 2014

Fortran module filenames

The Fortran standard does not define a rule as to the filename format of F90 module files. In fact, some (mostly old) compilers don't even use module files at all, instead embedding the modules within the object files.

The autoconf package provides a macro, AC_FC_MODULE_EXTENSION, which can be used to determine the file suffix of module files for a compiler, although currently it only handles cases when the file basename is the module name either in upper or lower case. However, there appears no macro that actually returns the format of the module file. For example a module named test could result in one of:
  • test.mod
  • TEST.mod
  • test.MOD
  • TEST.MOD
being created.

As a result I wrote a new macro MAY_FC_MODULE_FILENAME_FORMAT available here which returns the filename format of module files in the variable FC_MODFMT. For the cases listed above the values of FC_MODFMT returned are:
  • %m.mod
  • %M.mod
  • %m.MOD
  • %M.MOD

As mentioned there are other less common possibilities, these are not currently implemented but will be if I need them or if there is demand.

Hello world

1st post