Why is make complaining about circular dependencies? - makefile

I have built a make file for my project, and it works (everything compiles) but it gives these irritating error messages:
make: Circular zpr.c <- zpr.o dependency dropped.
gcc -Wall -c -o zpr.o zpr.c
make: Circular readjpeg.c <- readjpeg.o dependency dropped.
gcc -Wall -c -o readjpeg.o readjpeg.c
make: Circular readppm.c <- readppm.o dependency dropped.
gcc -Wall -c -o readppm.o readppm.c
make: Circular SceneNode.cpp <- SceneNode.o dependency dropped.
g++ -c -o SceneNode.o SceneNode.cpp
make: Circular BoundingBoxNode.cpp <- BoundingBoxNode.o dependency dropped.
g++ -c -o BoundingBoxNode.o BoundingBoxNode.cpp
make: Circular GeometryNode.cpp <- GeometryNode.o dependency dropped.
g++ -c -o GeometryNode.o GeometryNode.cpp
make: Circular SceneGraph.cpp <- SceneGraph.o dependency dropped.
g++ -c -o SceneGraph.o SceneGraph.cpp
make: Circular testgraph.cpp <- testgraph.o dependency dropped.
g++ -c -o testgraph.o testgraph.cpp
My makefile is not complicated at all so hopefully someone can spot the error.
GXX=g++
CC=gcc
CFLAGS=-Wall
LIBS=-lGL -lglut -ljpeg
OBJS=helpers.o loadobj.o zpr.o readjpeg.o readppm.o SceneNode.o BoundingBoxNode.o GeometryNode.o SceneGraph.o testgraph.o
OBJS2=testgraph.o SceneGraph.o GeometryNode.o BoundingBox.o SceneNode.o readppm.o readjpeg.o zpr.o loadobj.o helpers.o
SRCS=testgraph.cpp SceneGraph.cpp SceneNode.cpp
.o.cpp:
$(GXX) $(CFLAGS) -c $<
.o.c:
$(CC) $(CFLAGS) -c $<
testgraph: $(OBJS)
$(GXX) $(LIBS) $(OBJS) -o testgraph
clean:
rm *.o

Your implicit rules are the culprit. They have the extensions listed in the reverse order of how they are understood by make.
.o.c:
tells make that .c files are created from .o files. Since there is already a rule that says that .o files are created from .c files, you have a circular dependencies and therefore the errors.
The solution is (or should be, assuming a reasonably configured make) simple.
You don't (usually) need to specify your own rules for compilation in really common cases, such as C++ sources. It would be simpler to just specify something like:
CFLAGS=-Wall
LOADLIBES=-lGL -lglut -ljpeg
OBJS=helpers.o loadobj.o zpr.o readjpeg.o readppm.o SceneNode.o \
BoundingBoxNode.o GeometryNode.o SceneGraph.o testgraph.o
all: testgraph
testgraph: $(OBJS)
This is likely to also help you avoid two errors.
The rules you wrote say that .o files are created from .c files, which is backwards. But the correct rules already exist in nearly all versions of make.
You have listed the libraries ahead of the object files. This works by accident on some platforms that use ELF format objects. But it is still wrong. List libraries after objects because libraries are only loaded to satisfy undefined externals.

Related

Fortran makefile circular dependency dropped

So I am trying to run a Fortran code from someone else with the Intel Fortran compiler on a mac. But when I try to run the corresponding makefile, I get the error messages "make[1]: Circular release.makefile out <- release.makefile dependency dropped." and so on.
I have little knowledge of Fortran, so I would appreciate any help. I already tested to run some simple helloworld.f90 files and makefiles, to rule out that it is a compiler problem, and those work. However, the code I am trying to run is downloaded from a reputable scientific journal, so I assume the code (makefiles and Fortran files) should be correct too, leaving me at loss. This is my first stackoverflow post, so if I forgot something please let me know.
The makefile is:
release:
# ENV = /opt/intel/oneapi/setvars.sh intel64
make -f release.makefile
debug:
# ENV = /opt/intel/oneapi/setvars.sh intel64
make -f debug.makefile
dsymutil $(OUT).out
hpcrelease:
make -f hpcrelease.makefile
pbs:
make -f pbs.makefile
compilesubmit:
make -f hpcrelease.makefile
make -f pbs.makefile
qsub $(OUT).pbs
.PHONY: clean
clean:
rm -f *.o *.mod *.MOD *genmod* *~
rm -fr *.dSYM
and the file release.makefile writes:
FC = ifort
FCFLAGS = -m64 -traceback -O3 -qopenmp -implicitnone -Wl,-stack_size,0x100000000 -L/Users/josie/Desktop/Uni/Economics/Moll/SuiteSparse-master/lib -lumfpack -lamd -lcholmod -lcolamd -lsuitesparseconfig -lblas
LDFLAFS = -m64 -traceback -O3 -qopenmp -implicitnone -Wl,-stack_size,0x100000000 -L/Users/josie/Desktop/Uni/Economics/Moll/SuiteSparse-master/lib -lumfpack -lamd -lcholmod -lcolamd -lsuitesparseconfig -lblas
# -O3
PROG = $(OUT)
MOD = Parameters.o Globals.o umfpack.o Procedures.o
SUBR = AllocateArrays.o SetParameters.o Grids.o IterateBellman.o HJBUpdate.o cumnor.o rtsec.o StationaryDistribution.o SaveSteadyStateOutput.o DistributionStatistics.o rtbis.o rtflsp.o InitialSteadyState.o FinalSteadyState.o SolveSteadyStateEqum.o Calibration.o MomentConditions.o dfovec.o newuoa-h.o newuob-h.o update.o trsapp-h.o biglag.o bigden.o mnbrak.o golden.o sort2.o CumulativeConsumption.o FnDiscountRate.o OptimalConsumption.o FnHoursBC.o ImpulseResponses.o IRFSequence.o Transition.o SaveIRFOutput.o IterateTransitionStickyRb.o IterateTransOneAssetStickyRb.o FnCapitalEquity.o CumulativeConsTransition.o DiscountedMPC.o DiscountedMPCTransition.o
OBJ = $(MOD) $(SUBR)
$(PROG).out: $(OBJ) Main.o
$(FC) $(FCFLAGS) -o $# $^ $(LDFLAGS)
Main.o: $(MOD)
%: %.o
$(FC) $(FCFLAGS) -o $# $^ $(LDFLAGS)
%.o: %.f90
$(FC) $(FCFLAGS) -c $<
the error I get is
Fortran % make -f makefile
# ENV = /opt/intel/oneapi/setvars.sh intel64
make -f release.makefile
make[1]: Circular release.makefile.out <- release.makefile dependency dropped.
make[1]: Circular Main.f90.out <- Main.f90 dependency dropped.
make[1]: Circular Parameters.f90.out <- Parameters.f90 dependency dropped.
make[1]: Circular Globals.f90.out <- Globals.f90 dependency dropped.
make[1]: Circular umfpack.f90.out <- umfpack.f90 dependency dropped.
make[1]: Circular Procedures.f90.out <- Procedures.f90 dependency dropped.
make[1]: `Main.o' is up to date.
Since the error already occurs with the release.makefile, I refer from giving the other files since I believe the error is the same for all scripts? Correct me if I am wrong and those are necessary.

Can't use LAPACK in makefile

I have program (in fortran) where I'm using three custom modules, which make use of LAPACK. Until now I've compiled my program using the following shell script:
filestring="main"
gfortran -c mod_exp.f90 mod_genmat.f90 mod_print.f90 $filestring.f90
gfortran mod_exp.o mod_genmat.o mod_print.o $filestring.o -llapack -lblas
rm mod_exp.o mod_genmat.o mod_print.o $filestring.o exponentiate.mod genmat.mod printing.mod printing_subrtns.mod
mv a.out $filestring
Since I've been using more and more modules and different programs using them, I've decided to start using makefiles. Following a tutorial, I managed to write the following:
FC = gfortran
FFLAGS = -Wall -Wextra -llapack -lblas #-fopenmp
SOURCES = mod_print.f90 mod_genmat.f90 mod_exp.f90 main.f90
OBJ = ${SOURCES:.f90=.o} #substitute .f90 with .o
%.o : %.f90 #creation of all *.o files DEPENDS on *.f90
$(FC) $(FFLAGS) -c -O $< -o $#
main: $(OBJ)
$(FC) $(FFLAGS) -o $# $(OBJ)
clean:
#rm -f *.o *.mod main
However, when executing make, it says that the LAPACK functions are not recognized. One such mistake is the following:
/usr/bin/ld: mod_exp.o: in function `__exponentiate_MOD_diagun':
mod_exp.f90:(.text+0x37f): undefined reference to `zgees_'
...
collect2: error: ld returned 1 exit status
One possible mistake I've seen is that I need to specify the location of the libraries. However, it would seem strange since I didn't need to do it before; also, I don't know how to find it.
Please show the link command that make invoked, that caused the error to be generated.
I'm confident that if you cut and paste that exact command line to your shell prompt, you will get the same error you see when make runs it. So the problem is not make, but your link command.
The problem is that you have put the libraries before the objects in the link line. Libraries should come at the end, after the objects, else when the linker examines the libraries it doesn't know what symbols will need to be included (because no objects have been parsed yet to see what symbols are missing).
This is why LDLIBS is traditionally a separate variable:
FC = gfortran
FFLAGS = -Wall -Wextra #-fopenmp
LDLIBS = -llapack -lblas
SOURCES = mod_print.f90 mod_genmat.f90 mod_exp.f90 main.f90
OBJ = ${SOURCES:.f90=.o} #substitute .f90 with .o
%.o : %.f90 #creation of all *.o files DEPENDS on *.f90
$(FC) $(FFLAGS) -c -O $< -o $#
main: $(OBJ)
$(FC) $(FFLAGS) -o $# $(OBJ) $(LDLIBS)

Makefile: Circular - Dependency dropped

I have designed a Makefile that compiles all the .c files individually and produces a .o respectively (I think this happens Implicitly and works perfectly fine).
The executable (.out) is not being generated from the .o files.
Makefile:
TARGET = all.out
OBJS = file1.o file2.o file3.o
CC = gcc
CFLAGS = -g -Wall
all : $(TARGET)
$(TARGET) : $(OBJS)
# gcc $^ -o $#
run : $(TARGET)
./$<
clean :
rm -rf *.o $(TARGET)
Output:
$ make
make: Circular all.out <- all dependency dropped.
gcc -g -Wall -c -o file1.o file1.c
gcc -g -Wall -c -o file2.o file2.c
gcc -g -Wall -c -o file3.o file3.c
cp file1.o all.out
Note: The Makefile works perfectly and produces the perfect results if the line no. 7 present in it is uncommented.
line no. 7:
# gcc $^ -o $#
Output when line no. 7 is uncommented (Works perfectly as intended):
gcc -g -Wall -c -o file1.o file1.c
gcc -g -Wall -c -o file2.o file2.c
gcc -g -Wall -c -o file3.o file3.c
gcc file1.o file2.o file3.o -o a.out
I am new to Makefiles.
Queries:
why does commenting line no. 7 causing this issue and uncommenting it works perfectly?
What is cp in the first output when line no.7 was commented?
What does circular - dependency dropped mean?
I can't explain how you are seeing the problem you showed to us. Either what you wrote above is not actually what you're using, or you have a buggy version of GNU make. I can't reproduce the behavior you're seeing.
But, I'm sure it's related to this: GNU make has a built-in rule that knows how to build an xx.out file from a file xx for any xx:
# make -p -f/dev/null
...
%.out: %
# recipe to execute (built-in):
#rm -f $#
cp $< $#
If you comment out your own recipe as an explicit rule, then make will search for one among the pattern rules it knows about and it will find this built-in pattern rule.
However this rule shouldn't match based on what you've shown us: in order for it to match with a target of a.out, make would have to find or know how to build a target a and that doesn't seem to be available. Also, knowing how to build a would show a circular dependency on a.out.
If your makefile was:
TARGET = all.out
THEN it would all make perfect sense because you would have:
all : all.out
all.out : file1.o file2.o file3.o
and after the implicit rule match %.out: % it would expand like this:
all : all.out
all.out : all file1.o file2.o file3.o
#rm -f all.out
cp all all.out
So I assume that when you copied the output into your question you changed it: best to not do that. You should post exactly the problem you have (and verify you still have the problem with what you posted).

Compiling SDL project on Raspberry Pi

I am trying to build a project with make (gcc on Raspbian)
Here is the makefile (I removed some unnecessary parts):
objects = 3d.o Affichage.o [...]
cflags = -I/usr/local/include/SDL2 -L/usr/local/lib -lSDL2
poly : %(objects)
gcc $(cflags) $(objects) -o poly
($objects) : types.h
[...]
When running Make, I got:
cc -c -o Affichage.o Affichage.c
fatal error: SDL.h: No such file or directory
#include <SDL.h>
I checked the folders, everything seems ok. SDL.h is indeed in /usr/local/include/SDL2. I tried to remove options one by one in cflags, no luck...
What am I missing?
Make told you exact command it tried to execute:
cc -c -o Affichage.o Affichage.c
This don't have -I path, which is the source of an error.
You have target for your resulting executable but not for object files. Make have builtin rule to compile object files from C sources, but it isn't aware of your cflags variable. So far your options are:
Define your own pattern rule
e.g:
%.o: %.c
gcc $(cflags) -c $< -o $#
However, your cflags contains -lSDL2, which is linking flag, which should be specified only on linking phase (so technically it isn't cflag). Move it to separate variable (usually LIBS, which may then be enfolded into make's semi-standard LDFLAGS).
Use variables that make is aware of
In that case, it is CFLAGS:
CC:=gcc
CFLAGS:=-I/usr/local/include/SDL2
LIBS:=-lSDL2
LDFLAGS:=-L/usr/local/lib $(LIBS)
objects:=3d.o Affichage.o
poly: $(objects)
$(CC) $^ -o $# $(LDFLAGS)
$(objects): types.h
The rest will be done by implicit rules.

Adding functionality to Makefile gives error :- "multiple definitoon here ..."

I have been given an already working Makefile which is actually working fine.
Makefile Contents can be found here in this post ...
Questions about Makefile - what is "$+" & where are .c files/dependencies called here ?
I am asking this question separately from my previous post mentioned above as it involves a different issue and adding it to that question would unnecessarily increase its length.
Now I have added one more functionality which is being used quite frequently at many places so I thought creating a separate file would be a nice idea so I created linklayer.c and added linklayer.o to $LIBOBJS.
I added this ...
LIBOBJS= linklayer.o csum.o compact.o protoname.o headers.o
parseargs.o cryptomod.o crc32.o
and this
linklayer.o: linklayer.c
$(CC) -o $# -c -I. $(CFLAGS) $+
I have declared function in sendip_module.h which is already declared and accessed in each of the module present in the project.
But now this multiple definition error is coming ... Have I done something wrong or misunderstood something?
Note: "ipv6_opts" is defined in ipv6.h
$ make all
for subdir in mec ; do \
cd $subdir ;\
make ;\
cd .. ;\
done
make[1]: Entering directory `/home/udit/Desktop/sendip-2.5-mec-2/mec'
make[1]: Nothing to be done for `all'.
make[1]: Leaving directory `/home/udit/Desktop/sendip-2.5-mec-2/mec'
gcc-4.4 -o ipv6.so -fPIC -fsigned-char -pipe -Wall -Wpointer-arith
-Wwrite-strings -Wstrict-prototypes -Wnested-externs -Winline -Werror
-g -Wcast-align -DSENDIP_LIBS=\"/usr/local/lib/sendip\" -shared ipv6.c
libsendipaux.a libsendipaux.a
libsendipaux.a(linklayer.o):(.data.rel.local+0x0)
: multiple definition of `ipv6_opts'
/tmp/ccxa4tMX.o:(.data.rel.local+0x0): first defined here
collect2: ld returned 1 exit status
make: *** [ipv6.so] Error 1
and why this libsendipaux.a libsendipaux.a two times ? Is there something wrong with the Makefile itself.
Do I first need to manually compile it and then add it to libsendipaux.a ?
I am new to this Makefile stuff, so please help me understand how this is all working out here ?
Thanks.
Edit :
Remake debugging output -
remake -x
Reading makefiles...
Updating goal targets....
/home/udit/Desktop/sendip-2.5-mec-2/Makefile:33 File `all' does not exist.
/home/udit/Desktop/sendip-2.5-mec-2/Makefile:48 File `subdirs' does not exist.
/home/udit/Desktop/sendip-2.5-mec-2/Makefile:48 Must remake target `subdirs'.
for subdir in mec ; do \
cd $subdir ;\
make ;\
cd .. ;\
done
make[1]: Entering directory `/home/udit/Desktop/sendip-2.5-mec-2/mec'
make[1]: Nothing to be done for `all'.
make[1]: Leaving directory `/home/udit/Desktop/sendip-2.5-mec-2/mec'
/home/udit/Desktop/sendip-2.5-mec-2/Makefile:48 Successfully remade target file
`subdirs'.
File `ipv6.so' does not exist.
Must remake target `ipv6.so'.
gcc-4.4 -o ipv6.so -fPIC -fsigned-char -pipe -Wall -Wpointer-arith
-Wwrite-strings -Wstrict-prototypes -Wnested-externs -Winline -Werror
-g -Wcast-align -DSENDIP_LIBS=\"/usr/local/lib/sendip\" -shared ipv6.c
libsendipaux.a libsendipaux.a
libsendipaux.a(linklayer.o):(.data.rel.local+0x0)
: multiple definition of `ipv6_opts'
/tmp/ccb0oaXR.o:(.data.rel.local+0x0): first defined here
collect2: ld returned 1 exit status
remake: *** [ipv6.so] Error 1
#0 ipv6.so at ??
#1 all at /home/udit/Desktop/sendip-2.5-mec-2/Makefile:33
33rd line -> all: $(LIBS) subdirs sendip $(PROTOS) sendip.1 sendip.spec
I guess it could not help me out .... actual problem is with my understanding of scenario itself. Please help me bring out of the mess.
the problem you are facing, is that you are linking together several objects where at least two of them define de function ipv6_opts.
since there are two implementations of the function, your linker cannot decide which one to use and throws an error.
the problem most likely comes from the fact that you are linking libsendipaux.a twice into your final binary.
the reason why this happens is here:
%.so: %.c $(LIBS)
$(CC) -o $# $(CFLAGS) $(LIBCFLAGS) $+ $(LIBS)
in this target, $+ will expand to all the dependencies of your target (that is: %.c $(LIBS), which will in turn be resolved to ipv4.c libsendipaux.a
the actual call to the compiler can then be read as $(CC) -o $# $(CFLAGS) $(LIBCFLAGS) ipv4.c $(LIBS) $(LIBS), and $(LIBS) $(LIBS) will expand to libsendipaux.a libsendipaux.a, which will produce the erroneous double linkeage.
so the solution is to remove extraneous $(LIBS) from the .so target:
%.so: %.c $(LIBS)
$(CC) -o $# $(CFLAGS) $(LIBCFLAGS) $+
btw, the errors you get in remake about non-existing files, are because all and subdirs are indeed no files, but phony targets (targets that do no generate files called after the target-name).
to prevent those warnings, add something like the following to your makefile:
.PHONY: all subdirs

Resources