Reputation: 63
I have a project structure like this
-Project
--Common
---types.f90
---global.f90
---common_routines.f90
--Program 1
---program1.f90
---module1.f90
---module2.f90
---etc...
--Program 2
--etc...
Where, Common is folder that contains some modules that are shared across all programs. How do I include this modules on my makefile?
I tried this:
FC = gfortran
FCFLAGS = -fbounds-check -O3
FCFLAGS += -I ../Common
all: program1
program1: module1.o module2.o module3.o
program1.o: module1.o module2.o module3.o
module2.o: module1.o
module3.o: module2.o module1.o
%: %.o
$(FC) $(FCFLAGS) -o $@ $^
%.o: %.f90
$(FC) $(FCFLAGS) -c $<
clean:
rm -rf *.o *.mod
but I get an undefined reference error to the common modules variables.
Upvotes: 1
Views: 197
Reputation: 61282
I tried FCFLAGS += -I../Common types.o global.o common_routines.o
This will not work because -I
is an option to the GNU Fortran preprocessor
to specify a path that the preprocessor shall search for files to be INCLUDE-ed
prior to compilation. You cannot use it to specify a path where object files (*.o
)
will be searched for, after compilation, by the linker. It means nothing to
the linker and is not passed to the linker.
For simplicity let's assume that the object files you need to to link for
program1
are just program1/program1.o
plus the pre-existing common/types.o
,
common/global.o
and common/common_routines.o
Then the following Makefile
, placed in directory program1
, will build it:
OBJS = program1.o ../common/types.o ../common/global.o ../common/common_routines.o
.phony: all
all: program1
program1: program1.o
$(FC) -o $@ $(FCFLAGS) $(OBJS)
clean:
rm -f *.o program1
Just list all the required object files to the linker, in this case via $(OBJS)
You might wish to take the precaution of making sure that the common modules
are up to date before you build program1
, and you now might think that you can do that
simply be replacing:
program1: program1.o
with:
program1: $(OBJS)
thus prompting make
to recompile any of the four object files that is out
of date with respect to the corresponding source file, as a prerequisite of
building program1
make
will certainly endeavour to do that, but take care. That way, it will
recompile, say, ../common/types.o
from ../common/types.f90
just by its
implicit default recipe for making an .o
from an .f90
, since this makefile is
not telling it to do any different. But that may not be the way in which
../common/types.f90
is meant to be compiled, if you also have is a makefile in common
that stipulates how to do it in some non-default manner.
In that case, the common object files should always be compiled as per the
makefile in common
. Better leave the prerequisites of program1
alone but change the recipe to:
program1: program1.o
$(MAKE) -C ../common
$(FC) -o $@ $(FCFLAGS) $(OBJS)
Now, any time program1
needs to be rebuilt, the recipe will preemptively run make
in ../common
before it links the four object files. (It's a small inelegance that this $(MAKE) -C ../common
will be invoked even if there's nothing for it to do: this is avoidable by more advanced make
usage).
Lastly you might also find a need (if not in this case, then in another) to distinguish
between flags passed to preprocessing and/or flags passed to compilation and/or flags passed to linkage.
Conventionally, these are assigned to distinct make
variables, e.g. FPPFLAGS
(preprocessor),
FCFLAGS
(compiler), LDFLAGS
(linker).
Upvotes: 2
Reputation: 10165
The GNU syntax to define additional include directory is -Idir
not -I dir
(extra space)
Also make sure that common modules are already compiled and include search path points to the directory where you have compiled modules, not source files:
This path is also used to search for .mod files when previously compiled modules are required by a USE statement.
Upvotes: 0