Reputation: 131
I have a problem writing a Makefile.am that will make autotools compile files in the correct order.
My minimal example is some test.f90
which uses routines from a module mod.f90
. By hand, I do the following.
gfortran -c mod.f90
gfortran -c test.f90
gfortran -o test test.o mod.o
This works fine. Now, I have read that autotools does not handle Fortran module dependencies and, according to this post (automake with fortran: order of file) one should just put the dependencies into Makefile.am by hand.
Mine looks like the following.
AUTOMAKE_OPTIONS = foreign
bin_PROGRAMS = test
test_SOURCES = mod.f90 test.f90
test: test.f90 mod.o
mod.o: mod.f90
While the .mod file for the module is generated each time I run ./configure && make
, it is apparently not generated before all the other files, i.e. I still get the error message Fatal Error: Cannot open module file ‘mod.mod’ for reading at (1): No such file or directory
.
Running ./configure && make
twice in a row allows the programme to be compiled but of course this is not really a satisfying solution. Is there some standard way to deal with this? Can I maybe somehow force mod.o
to be compiled before test.o
?
Upvotes: 2
Views: 481
Reputation: 181149
The second of these two lines is redundant in light of the first:
test_SOURCES = mod.f90 test.f90 test: test.f90 mod.o
This one is unneeded, because Automake (and GNU make
) already know the information it conveys:
mod.o: mod.f90
That effectively leaves you with just this:
AUTOMAKE_OPTIONS = foreign
bin_PROGRAMS = test
test_SOURCES = mod.f90 test.f90
That's ok as far as it goes, but it does not express any dependency information related to the mod.mod
file, so builds may fail. To fix that, you need to add one or more rules that express the additional dependencies and how to satisfy them.
The true dependency is that test.o
depends on mod.mod
, and you could write a dependency-only rule expressing that:
# INSUFFICIENT
test.o: mod.mod
But that leaves you with a problem: make
doesn't know that mod.mod
is an output of the compilation of mod.f90
. Indeed, situations where multiple targets are created by one run of a recipe are problematic to describe to make
(and Automake). The Automake manual devotes one of its lengthier sections to this issue. The most robust possible build system would use an approach such as that section describes to express how to build mod.o
and mod.mod
, but that would about triple the size of your Makefile.am
, and you would need similar extra code for every Fortran module.
You can achieve a fairly good workaround by instead telling Automake that test.o
depends on mod.o
:
# Better
test.o: mod.o
That will yield successful builds from scratch, and under most normal development circumstances, but it does express an incorrect dependency. As a result, it is susceptible to build breakage by, for example, building the project, then removing mod.mod
(leaving mod.o
in place) and updating test.f90
. On subsequent builds, make
will then see that mod.o
is up to date, so it will do nothing to regenerate the missing mod.mod
. A clean build would rescue that, and as a developer, I would probably be prepared to accept that situation for the sake of Makefile.am
simplicity.
Speaking of a clean build, you should also add mod.mod
to the list of files that make clean
should remove:
CLEANFILES = mod.mod
Overall, then, the final result is:
AUTOMAKE_OPTIONS = foreign
bin_PROGRAMS = test
test_SOURCES = mod.f90 test.f90
# A fib -- the real dependency is test.o: mod.mod
test.o: mod.o
CLEANFILES = mod.mod
Upvotes: 2