I have been looking at this problem for a while and still don't know what is wrong.
My makefile looks like:
F90 = pgf90
NETCDF_DIR = /opt/netcdf
LBS = -L$(NETCDF_DIR)/lib -lnetcdff -lnetcdf
INCLUDE_MODULES = -I$(NETCDF_DIR)/include
EXEC = CNG_WRFCHEM_EMI
OBJS = module_CNG_WRFCHEM_EMI_lib.o \
CNG_WRFCHEM_EMI.o
${EXEC} : ${OBJS}
${F90} -o $# ${OBJS} ${LIBS}
.f90.o:
${F90} -c ${INCLUDE_MODULES} $<
clean:
rm -f ${EXEC} ${OBJS} *.mod
The error message is:
make: *** No rule to make target `module_CNG_WRFCHEM_EMI_lib.o', needed by `CNG_WRFCHEM_EMI'. Stop.
All the files are in the same directory as the picture shows:
thanks
Make doesn't know that .f90 is a suffix, so your suffix rule is not valid. It's not enough to just declare a suffix rule if make doesn't know about the suffix. If you want to use suffix rules, you also have to add the new suffix with the .SUFFIXES pseudo-target, like this:
.SUFFIXES: .f90
Or you can use pattern rules, which don't require this (but are GNU make-specific):
%.o : %.f90
${F90} -c ${INCLUDE_MODULES} $<
Related
I have been looking at this problem for a while and still don't know what is wrong.
My makefile looks like:
F90 = pgf90
NETCDF_DIR = /opt/netcdf
LBS = -L$(NETCDF_DIR)/lib -lnetcdff -lnetcdf
INCLUDE_MODULES = -I$(NETCDF_DIR)/include
EXEC = CNG_WRFCHEM_EMI
OBJS = module_CNG_WRFCHEM_EMI_lib.o \
CNG_WRFCHEM_EMI.o
${EXEC} : ${OBJS}
${F90} -o $# ${OBJS} ${LIBS}
.f90.o:
${F90} -c ${INCLUDE_MODULES} $<
clean:
rm -f ${EXEC} ${OBJS} *.mod
The error message is:
make: *** No rule to make target `module_CNG_WRFCHEM_EMI_lib.o', needed by `CNG_WRFCHEM_EMI'. Stop.
All the files are in the same directory as the picture shows:
thanks
Make doesn't know that .f90 is a suffix, so your suffix rule is not valid. It's not enough to just declare a suffix rule if make doesn't know about the suffix. If you want to use suffix rules, you also have to add the new suffix with the .SUFFIXES pseudo-target, like this:
.SUFFIXES: .f90
Or you can use pattern rules, which don't require this (but are GNU make-specific):
%.o : %.f90
${F90} -c ${INCLUDE_MODULES} $<
The following example makefile works as expected, using vpath to find object files and source files. But in the last line, where i tell make about the dependency of one object file on the other, I need to specify the directory $(objd)/ of the prerequisite file, otherwise i get an error (see error message below the code). How come the vpath directive isn't sufficient in the last line?
# Program Name
prog = avpar
#dirs
objd=obj
modd=mod
# extra places to search for prerequisites
vpath %.f90 ../modules
vpath %.o obj/
# etc
FC = gfortran
flags = -I$(modd) -J$(modd) #-fopenmp
obj_files = $(prog).o rw_mod.o
# compile
p$(prog): $(obj_files)
$(FC) $(flags) $^ -o $#
$(objd)/%.o: %.f90
$(FC) $(flags) -c $< -o $#
$(objd)/$(prog).o: $(objd)/rw_mod.o
That is, changing the last line to:
$(objd)/$(prog).o: rw_mod.o
gives the error:
make: *** No rule to make target 'rw_mod.o', needed by 'obj/avpar.o'. Stop.
EDIT
with this form of the last lines it does also work, without the directory specification:
#compile
p$(prog): $(obj_files)
$(FC) $(flags) $^ -o $#
$(objd)/rw_mod.o: rw_mod.f90
$(FC) $(flags) -c $< -o $#
$(objd)/$(prog).o: $(prog).f90 rw_mod.o
$(FC) $(flags) -c $< -o $#
vpath can only be used to find prerequisites that exist.
Makefiles rule 3
Use VPATH to locate the sources from the objects directory, not to locate the objects from the sources directory.
There's no rule that matches rw_mod.o so the rule for obj/avpar.o fails, vpath won't prepend stuff during prerequisite rule lookup, the only way it would work here would be if obj/rw_mod.o already existed.
It's unlikely that rule is correct anyway, why would one object file depend on another?
I am trying to update some old Fortran code and I want to use a makefile to build it. Right now, my makefile looks like
FC = gfortran
FFLAGS = -O2
HDRS = global.h param.h coor.h
SRCS = xxx.f yyy.f zzz.f newstuff.f90 main.f
OBJS = $(SRCS:.f=.o)
OBJS := $(OBJS:.f90=.o)
runit: $(OBJS)
$(FC) $(FFLAGS) -o $# $^
xxx.o yyy.o main.o : global.h
yyy.o zzz.o: coor.h
xxx.o yyy.o zzz.o main.o : param.h
xxx.o main.o : newstuff.o
clean:
rm runit *.o *.mod
.SUFFIXES: .f .f90 .o
.f.o:
$(FC) $(FFLAGS) -c $<
.f90.o:
$(FC) $(FFLAGS) -c $<
I have two questions. First, I edit newstuff.f90 and then issue make newstuff.o, expecting a new newstuff.o. Instead, I get the message that newstuff.o is up to date. This doesn't happen with any of the other source codes. What do I have to do to convince make that newstuff.o is indeed out of date?
Second, trying to hack a fix, I inserted the line (not shown above): newstuff.o : newstuff.f90. But with that line in the makefile, make returns
m2c -o mpi_wrapper.o mpi_wrapper.mod
make: m2c: No such file or directory
Why does make go for this other utility m2c, whatever that is? How do I convince it to use gfortran? Thanks.
there is a default rule treating mod files as Modula files. You can disable this rule by adding this following line followed by a blank line to your Makefile:
%.o : %.mod
The following is a working make; it is a simplified version of a more complex one, but it manages to reproduce the problems when I try some changes. Files "myobj.f" and "mymod.f" are in folders "src1" and "src2" respectively and are almost empty (mymod is a module that has a variable declared and myobj is a subroutine that initializes and prints that variable).
I tried googling for this, but all circular dependency errors I found seemed more clear than this. Could you please help me identify what is wrong with my makefile?
all : mylib.so
makefiles := Makefile
FC = gfortran
FFLAGS = -I$(obj_path) -J$(obj_path) -fPIC
LFLAGS = -shared -fPIC
obj_path := obj
src_paths = src1 src2
vpath %.o $(obj_path)
vpath %.mod $(obj_path)
vpath %.f $(src_paths)
objects = myobj.o mymod.o
obj/myobj.o : obj/mymod.mod
mylib.so : $(objects:%.o=$(obj_path)/%.o)
$(FC) $(LFLAGS) $^ $(LIBS) -o $#
$(obj_path)/%.mod : %.o
#touch $#
$(obj_path)/%.o : %.f $(makefiles) | $(obj_path)
$(FC) $(FFLAGS) -c $< -o $#
$(obj_path) :
mkdir -p $#
.PHONY: clean
clean:
rm -rf mylib.so $(obj_path)
(1) I can't simplify the rules
Having the "$(obj_path)" explicitly in the rules for compiling objects seems unnecessary: I know vpath does not work with files that change during compile time and was designed only for sources, but I don't see why clarifying the path when I list the objects as dependencies of the library shouldn't suffice.
mylib.so : $(objects:%.o=$(obj_path)/%.o)
$(FC) $(LFLAGS) $^ $(LIBS) -o $#
%.mod : %.o
#touch $#
%.o : %.f $(makefiles) | $(obj_path)
$(FC) $(FFLAGS) -c $< -o $#
But this doesn't work; I get a circular dependency dropped warning and make tries to compile the modules using m2c. Just in case, commenting the vpaths for .o and .mod does not fix this. Output of make --debug:
Reading makefiles...
Updating goal targets....
File 'all' does not exist.
File 'mylib.so' does not exist.
File 'obj/myobj.o' does not exist.
make: Circular obj/myobj.mod <- obj/myobj.o dependency dropped.
File 'obj/mymod.mod' does not exist.
File 'obj/mymod.o' does not exist.
make: Circular obj/mymod.o <- obj/mymod.mod dependency dropped.
Must remake target 'obj/mymod.o'.
m2c -o obj/mymod.o
make: m2c: Command not found
<builtin>: recipe for target 'obj/mymod.o' failed
make: *** [obj/mymod.o] Error 127
(2) I can't add a rule for f90
Now I want to be able to incorporate f90 code to my library. Adding the rule seems not to affect the process if nothing else changes, but when I change the extension of mymod.f to mymod.f90, it returns a similar error that the other case. The modified section is:
$(obj_path)/%.mod : %.o
#touch $#
$(obj_path)/%.o : %.f $(makefiles) | $(obj_path)
$(FC) $(FFLAGS) -c $< -o $#
$(obj_path)/%.o : %.f90 $(makefiles) | $(obj_path)
$(FC) $(FFLAGS) -c $< -o $#
And the output of make --debug is this:
Reading makefiles...
Updating goal targets....
File 'all' does not exist.
File 'mylib.so' does not exist.
File 'obj/myobj.o' does not exist.
File 'obj' does not exist.
Must remake target 'obj'.
mkdir -p obj
Successfully remade target file 'obj'.
File 'obj/mymod.mod' does not exist.
File 'obj/mymod.o' does not exist.
make: Circular obj/mymod.o <- obj/mymod.mod dependency dropped.
Must remake target 'obj/mymod.o'.
m2c -o obj/mymod.o
make: m2c: Command not found
<builtin>: recipe for target 'obj/mymod.o' failed
make: *** [obj/mymod.o] Error 127
COMPILATION CONFIG 1:
Makefile:
all : mylib.so
makefiles := Makefile
FC = gfortran
FFLAGS = -I$(obj_path) -J$(obj_path) -fPIC
LFLAGS = -shared -fPIC
obj_path := obj
src_paths = src1 src2
#vpath %.o $(obj_path)
#vpath %.mod $(obj_path)
vpath %.f $(src_paths)
objects = myobj.o mymod.o
obj/myobj.o : obj/mymod.mod
mylib.so : $(objects:%.o=$(obj_path)/%.o)
$(FC) $(LFLAGS) $^ $(LIBS) -o $#
%.mod : %.o
#touch $#
%.o : %.f $(makefiles) | $(obj_path)
$(FC) $(FFLAGS) -c $< -o $#
$(obj_path) :
mkdir -p $#
.PHONY: clean
clean:
rm -rf mylib.so $(obj_path)
src1/myobj.f:
subroutine myobj
use mymod
implicit none
mymodx=1
print*,'mymod was included', mymodx
return
end subroutine
src2/mymod.f:
module mymod
implicit none
integer :: mymodx
end module
Terminal output:
make --debug
GNU Make 4.1
Built for x86_64-unknown-linux-gnu
Copyright (C) 1988-2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Reading makefiles...
Updating goal targets....
File 'all' does not exist.
File 'mylib.so' does not exist.
File 'obj/myobj.o' does not exist.
make: Circular obj/myobj.mod <- obj/myobj.o dependency dropped.
File 'obj/mymod.mod' does not exist.
File 'obj/mymod.o' does not exist.
make: Circular obj/mymod.o <- obj/mymod.mod dependency dropped.
Must remake target 'obj/mymod.o'.
m2c -o obj/mymod.o
make: m2c: Command not found
<builtin>: recipe for target 'obj/mymod.o' failed
make: *** [obj/mymod.o] Error 127
There are a few issues with your approach. The vpath searching only applies to pre-requisites and not targets, so a rule like
%.o: %.f
will search the $(src_paths) for the source but it will not attempt to match targets in $(obj_path). This leads to the next issue, that due to putting objects into an intermediate directory, your rule needs to account for this since vpath won't help. Your main target to build the library depends on things like $(obj_path)/blah.f so you want to use a rule like:
$(obj_path)/%.o: %.f
to match the objects. There may be a cleaner way to do this, but I am not aware of them.
Likewise, the rule with the %.mod target was not matching the requirement in the object directory and it looks like a default implicit rule was being called to handle them, attempting to invoke m2c.
Specifically, make tries to compile the mod file as modula-2 source and its automatic rule to do this conflicted with your %.o:%.mod rule and produced the circular dependency.
By modifying that rule to properly match the mod files, this mess is avoided.
Also, dont forget to add a vpath for %.f90, so your rules can find those source files.
I can successfully build your test project with this slightly modified Makefile. I also used files named .f90 to show that it also solves your second issue.
FC = gfortran
FFLAGS = -I$(obj_path) -J$(obj_path) -fPIC
LFLAGS = -shared -fPIC
src_paths = src1 src2
obj_path := obj
vpath %.o $(obj_path)
vpath %.mod $(obj_path)
vpath %.f90 $(src_paths)
vpath %.f $(src_paths)
mylib_objects = myobj.o mymod.o
mylib_target = mylib.so
all: $(mylib_target)
$(mylib_target) : $(mylib_objects:%.o=$(obj_path)/%.o)
$(FC) $(LFLAGS) $^ $(LIBS) -o $#
$(obj_path)/myobj.o: myobj.f90 $(obj_path)/mymod.mod
$(obj_path) :
mkdir -p $#
$(obj_path)/%.mod : %.o $(obj_path)
#true
$(obj_path)/%.o: %.f | $(obj_path)
$(FC) $(FFLAGS) -c $< -o $#
$(obj_path)/%.o: %.f90 | $(obj_path)
$(FC) $(FFLAGS) -c $< -o $#
clean:
rm -rf $(mylib_target) $(obj_path)
From a clean start, the output of make --debug is:
% make --debug
GNU Make 4.1
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Reading makefiles...
Updating goal targets....
File 'all' does not exist.
File 'mylib.so' does not exist.
File 'obj/myobj.o' does not exist.
File 'obj' does not exist.
Must remake target 'obj'.
mkdir -p obj
Successfully remade target file 'obj'.
File 'obj/mymod.mod' does not exist.
File 'obj/mymod.o' does not exist.
Must remake target 'obj/mymod.o'.
gfortran -Iobj -Jobj -fPIC -c src2/mymod.f90 -o obj/mymod.o
Successfully remade target file 'obj/mymod.o'.
Must remake target 'obj/mymod.mod'.
Successfully remade target file 'obj/mymod.mod'.
Must remake target 'obj/myobj.o'.
gfortran -Iobj -Jobj -fPIC -c src1/myobj.f90 -o obj/myobj.o
Successfully remade target file 'obj/myobj.o'.
Must remake target 'mylib.so'.
gfortran -shared -fPIC obj/myobj.o obj/mymod.o -o mylib.so
Successfully remade target file 'mylib.so'.
Must remake target 'all'.
Successfully remade target file 'all'.
Also note that you can instead handle your module dependency by stipulating the object files in an other that guarantees necessary mod files will have been generated. For example, changing
objects = myobj.o mymod.o
to
objects = mymod.o myobj.o
makes the rules and pre-requisites involving the mod files un-necessary, as this will cause mymod.o (and the byproduct mymod.mod) to be built before myobj.o is attempted. It is possible that this solution would break in a parallel build, so I have maintained your object ordering and made sure the rules worked as intended.
I'm just getting back into the world of Makefiles and have a vexing problem: adding a $*.h prerequisite on a rule for generating the corresponding .o file always results in "nothing to be done". Below is my Makefile in its entirety:
SOURCES := mu.cpp node.cpp test_node.cpp transport.cpp
OBJECT_DIR := ../obj
INCLUDE_DIR := ../include
OBJECTS := $(patsubst %.cpp,$(OBJECT_DIR)/%.o,$(SOURCES))
CC = g++
DEFS =
CFLAGS = -O3 -Wall
IFLAGS = -I$(INCLUDE_DIR) -I../tarballs/stk-4.4.4/include
$(OBJECT_DIR)/%.o : %.cpp $(INCLUDE_DIR)/mu.h $(INCLUDE_DIR)/$*.h
$(CC) $(CFLAGS) $(IFLAGS) -c $(<) -o $#
all: $(OBJECTS)
clean:
rm -f $(OBJECT_DIR)/*.o
$(OBJECTS): | $(OBJECT_DIR)
$(OBJECT_DIR):
mkdir $(OBJECT_DIR)
If I type make all using the above, make always responds with "nothing to be done for 'all'" But if I change the rule that reads:
$(OBJECT_DIR)/%.o : %.cpp $(INCLUDE_DIR)/mu.h $(INCLUDE_DIR)/$*.h
to
$(OBJECT_DIR)/%.o : %.cpp $(INCLUDE_DIR)/mu.h
(i.e., I remove foo.cpp's dependency on ../include/foo.h), then make all responds as expected. The problem with this, of course, is that foo.cpp will not be recompiled if ../include/foo.h has been modified more recently than foo.cpp.
FWIW, I've verified that $(INCLUDE_DIR)/$*.h expands to the proper file name.
I'm pretty sure this is something obvious. Any hints?
Automatic variables like $* are not defined anywhere except in the recipe of the rule. You cannot use them in the prerequisites list.
Why don't you just use the pattern in both cases?
$(OBJECT_DIR)/%.o : %.cpp $(INCLUDE_DIR)/%.h $(INCLUDE_DIR)/mu.h