Author: Balaji, SGI/GFDL.
Features of mkmf include:
mkmf is pronounced make-make-file or make-m-f or even McMuff (Paul Kushner's suggestion).
The calling syntax is:
mkmf [-a abspath] [-c cppdefs] [-d] [-f] [-m makefile] [-p program] [-t template] [-v] [-x] [args]
A sourcefile is any file with a source file suffix (currently .F, .F90, .c, .cc, .cpp, .f. .f90). An includefile is any file with an include file suffix (currently .H, .fh, .h, .hh, .inc, .h90). A valid sourcefile can also be an includefile.
Each sourcefile in the list is presumed to produce an object file with the same basename and a .o extension in the current working directory. If more than one sourcefile in the list would produce identically-named object files, only the first is used and the rest are discarded. This permits the use of overlays: if dir3 contained the basic source code, dir2 contained bugfixes, and dir1 contained mods for a particular run, mkmf dir1 dir2 dir3 would create a makefile for correct compilation. Please note that precedence descends from left to right. This is the conventional order used by compilers when searching for libraries, includes, etc: left to right along the command line, with the first match invalidating all subsequent ones. See the Examples section for a closer look at precedence rules.
The makefile currently runs $(FC) on fortran files,
$(CC) on C files and $(CXX) on C++ files. Flags to the compiler can be set
in $(FFLAGS) or $(CFLAGS) or In addition, the macro $(CPPDEFS) is applied to the
preprocessor. This can contain the cpp #defines which
may change from run to run. cpp options that do not
change between compilations should be placed in
$(CPPFLAGS).
Includefiles are recursively searched for embedded includes.
For emacs users, the make target
TAGS is always provided. This creates a TAGS file in
the current working directory with a cross-reference table linking all
the sourcefiles. If you don't know about emacs tags, please consult
the emacs help files! It is an incredibly useful feature.
The default action for non-existent files is to touch them
(i.e create null files of that name) in the current working directory.
All the object files are linked to a single executable. It is
therefore desirable that there be a single main program source among
the arguments to mkmf, otherwise, the loader is likely to
complain.
The argument list args is treated sequentially from
left to right. Arguments can be of three kinds:
This will add a.f90, b.f90 and c.f90 to the
sourcefile list. The first two files will be compiled using the
generic command $(FC) $(FFLAGS). But when the make requires
c.f90 to be compiled, it will be compiled with f90
-Oaggress.
The current working directory is always the first (and
top-precedence) argument, even if args is not supplied.
The argument cppdefs is treated as
follows. cppdefs should contain a comprehensive list
of the cpp #defines to be
preprocessed. This list is compared against the current "state",
maintained in the file .cppdefs in the current
working directory. If there are any changes to this state,
mkmf will remove all object files
affected by this change, so that the subsequent make
will recompile those files. Previous versions of mkmf
attempted to touch the relevant source, an operation
that was only possible with the right permissions. The current version
works even with read-only source.
The file .cppdefs is created if it does not exist. If you
wish to edit it by hand (don't!) it merely contains a list of the
cpp flags separated by blanks, in a single record, with no
newline at the end.
cppdefs also sets the make macro
CPPDEFS. If this was set in a template file and also
in the -c flag to mkmf, the value in
-c takes precedence. Typically, you should set only
CPPFLAGS in the template file, and
CPPDEFS via mkmf -c.
Include files are often specified without an explicit path, e.g
mkmf first attempts to locate the includefile in the same
directory as the source file. If it is not found there, it looks in
the directories listed as arguments, maintaining the same
left-to-right precedence as described above.
This follows the behaviour of most f90 compilers: includefiles
inherit the path to the source, or else follow the order of include
directories specified from left to right on the f90 command
line, with the -I flags descending in precedence from
left to right.
If you have includefiles in a directory dir other than
those listed above, you can specify it yourself by including
-Idir in $(FFLAGS) in your template
file. Includepaths in the template file take precedence over those
generated by mkmf. (I suggest using
FFLAGS for this rather than CPPFLAGS
because fortran includes can occur even in source
requiring no preprocessing).
Sample template files for different OSs and compilers are available in
the directory /net/vb/public/bin.
The directory /home/src/base contains the files:
Typing Note that when files of the same name recur in the target list, the
files in the updates directory (specified in
path_names) are used rather than those in the base source
repository /home/src/base.
Assume that now you want to test some changes to c.f90. You
don't want to make changes to the base source repository itself prior
to testing; so you make yourself a local copy.
You didn't even need to know where c.f90 originally was.
Now you can make changes to your local copy ./c.f90. To
compile using your changed copy, type:
Note that you are now using your local copy of c.f90 for
the compile, since the files in the current working directory always
take precedence. To revert to using the base copy, just remove the
local copy and run mkmf again.
will set CPPDEFS to this value, and also save this
state in the file .cppdefs. If the argument to
-c is changed in a subsequent call:
it would confuse mkmf. Similarly, a fortran
include statement must not be split across lines.
is to be avoided.
Please address all inquires to Balaji,
SGI/GFDL.
Treatment of [args]:
a.f90
b.f90
f90 -Oaggress c.f90
Treatment of [-c cppdefs]:
Treatment of includefiles:
#include "config.h"
FC = f90
LD = f90
CPPFLAGS = -macro_expand
FFLAGS = -d8 -64 -i4 -r8 -mips4 -O3
LDFLAGS = -64 -mips4 $(LIBS)
LIST = -listing
The meaning of the various flags may be divined by reading the
manual. A line defining the make macro LIBS, e.g:
LIBS = -lmpi
may be added anywhere in the template to have it added to the link
command line.
updates/a.f90
updates/b.f90
a.f90
b.f90
c.f90
mkmf path_names /home/src/base
produces the
following Makefile:
# Makefile created by mkmf $Id: mkmf.html,v 1.1.2.1 2013/12/18 17:47:54 Niki.Zadeh Exp $
.DEFAULT:
-touch $@
all: a.out
c.o: /home/src/base/c.f90
$(FC) $(FFLAGS) -c /home/src/base/c.f90
a.o: updates/a.f90
$(FC) $(FFLAGS) -c updates/a.f90
b.o: updates/b.f90
$(FC) $(FFLAGS) -c updates/b.f90
./c.f90: /home/src/base/c.f90
cp /home/src/base/c.f90 .
./a.f90: updates/a.f90
cp updates/a.f90 .
./b.f90: updates/b.f90
cp updates/b.f90 .
SRC = /home/src/base/c.f90 updates/a.f90 updates/b.f90
OBJ = c.o a.o b.o
OFF = /home/src/base/c.f90 updates/a.f90 updates/b.f90
clean: neat
-rm -f .cppdefs $(OBJ) a.out
neat:
-rm -f $(TMPFILES)
localize: $(OFF)
cp $(OFF) .
TAGS: $(SRC)
etags $(SRC)
tags: $(SRC)
ctags $(SRC)
a.out: $(OBJ)
$(LD) $(OBJ) -o a.out $(LDFLAGS)
make ./c.f90
mkmf path_names /home/src/base
make
The new Makefile looks like this:
# Makefile created by mkmf $Id: mkmf.html,v 1.1.2.1 2013/12/18 17:47:54 Niki.Zadeh Exp $
.DEFAULT:
-touch $@
all: a.out
c.o: c.f90
$(FC) $(FFLAGS) -c c.f90
a.o: updates/a.f90
$(FC) $(FFLAGS) -c updates/a.f90
b.o: updates/b.f90
$(FC) $(FFLAGS) -c updates/b.f90
./a.f90: updates/a.f90
cp updates/a.f90 .
./b.f90: updates/b.f90
cp updates/b.f90 .
SRC = c.f90 updates/a.f90 updates/b.f90
OBJ = c.o a.o b.o
OFF = updates/a.f90 updates/b.f90
clean: neat
-rm -f .cppdefs $(OBJ) a.out
neat:
-rm -f $(TMPFILES)
localize: $(OFF)
cp $(OFF) .
TAGS: $(SRC)
etags $(SRC)
tags: $(SRC)
ctags $(SRC)
a.out: $(OBJ)
$(LD) $(OBJ) -o a.out $(LDFLAGS)
mkmf -c "-Dcppflag -Dcppflag2=2 -Dflag3=string ..."
mkmf -c "-Dcppflag -Dcppflag2=3 -Dflag3=string ..."
mkmf will scan the source list for sourcefiles that make
references to cppflag2, and the corresponding object files
will be removed.
Caveats:
use &
this_moduleuse module1; use module2
#ifdef obsolete
#include "nonexistent.h"
#endif
Changes
The RCS log for
mkmf contains a comprehensive list of changes. In the
unlikely event that you should wish to check out a retro version,
please get in touch with me, Balaji.
TODO:
Author: V. Balaji
Document last modified