Makefile: Circular - Dependency dropped - makefile

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).

Related

Preventing Makefile target recompiling

I have the following Makefile. For some reason when I do make it always rebuilds the target test_phantom_types.o even when I haven't modified the files.
GTEST_HEADERS = ${GTEST_DIR}/include/gtest/*.h \
${GTEST_DIR}/include/gtest/internal/*.h
BASE_DIR = ..
BUILD_DIR = build
USER_DIR = $(BASE_DIR)/tests/src
CPPFLAGS += -isystem $(GTEST_DIR)/include
CXXFLAGS += -g -Wall -Wextra -pthread -std=c++11
TESTS = test_phantom_types
all : $(TESTS)
clean :
cd $(BUILD_DIR); \
rm -rf $(BUILD_DIR)/*.o; \
cd ../
test_phantom_types.o : $(USER_DIR)/test_phantom_types.cpp \
$(BASE_DIR) $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(BASE_DIR) -c $(USER_DIR)/test_phantom_types.cpp -o $(BUILD_DIR)/$#
test_phantom_types : test_phantom_types.o
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $(addprefix $(BUILD_DIR)/,$^) ${GTEST_DIR}/libgtest.a ${GTEST_DIR}/libgtest_main.a -o $(addprefix $(BUILD_DIR)/, $#)
check : $(TESTS)
./$(addprefix $(BUILD_DIR)/,$^)
.PHONY : clean
make is very literal.
You told it you have a target called test_phantom_types.o so it expects that target to generate that file.
In your case, however, it doesn't. It generates $(BUILD_DIR)/$# (from -o $(BUILD_DIR)/$#) and that's not the same thing.
So when you run make and make determines (from the all -> test_phantom_types -> test_phantom_types.o sequence) that it needs to check if it needs to build the test_phantom_types.o file it goes to look for it, can't find it and rebuilds it.
You can see this in the output from make -d if you try it.
That's why the second Rule of Makefiles is
2.Every non-.PHONY rule must update a file with the exact name of its target.
Make sure every command script touches the file “$#“–not “../$#“, or “$(notdir $#)“, but exactly $#. That way you and GNU make always agree.

Some implicit makefile?

I am trying to understand makefile.
I took atmega168 bootloader's makefile and simplified it to this:
CC = avr-gcc
override CFLAGS = -g -Wall -Os -mmcu=atmega328p -DF_CPU=16000000L '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' -DBAUD_RATE=57600
atmega328: ATmegaBOOT_168_atmega328.hex
%.elf: ATmegaBOOT_168.o
avr-gcc -g -Wall -Os -mmcu=atmega328p -DF_CPU=16000000L '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' -DBAUD_RATE=57600 -Wl,--section-start=.text=0x7800 -o $# $<
clean:
rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex
%.hex: %.elf
avr-objcopy -j .text -j .data -O ihex $< $#
When I ran $ make atmega328 I get:
avr-gcc -g -Wall -Os -mmcu=atmega328p -DF_CPU=16000000L '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' -DBAUD_RATE=57600 -c -o ATmegaBOOT_168.o ATmegaBOOT_168.c
avr-gcc -g -Wall -Os -mmcu=atmega328p -DF_CPU=16000000L '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' -DBAUD_RATE=57600 -Wl,--section-start=.text=0x7800 -o ATmegaBOOT_168_atmega328.elf ATmegaBOOT_168.o
avr-objcopy -j .text -j .data -O ihex ATmegaBOOT_168_atmega328.elf ATmegaBOOT_168_atmega328.hex
rm ATmegaBOOT_168_atmega328.elf ATmegaBOOT_168.o
Why cannot I remove CC or CFLAGS?
I understand some basics of makefile. I read a lot on the internet, plus went through gnu manual, but I cannot understand the very first output with ATmegaBOOT_168.c. What/How has generated first command?
Was there used some second makefile? If yes, how to find its location?
UPDATE:
If I rename ATmegaBOOT_168.c to ATmegaBOOT_1681.c. Running $ make atmega328 gives:
make: *** No rule to make target 'ATmegaBOOT_168_atmega328.hex', needed by 'atmega328'. Stop.
but the rule is present.
CC and CFLAGS are variables used in the built in implicit rules of GNU make. When you run make, it reads your makefile a bit like:
No target given, so we'll make the first: atmega328. This requires a .hex file.
The .hex file can be generated from a .elf file per the last rule.
.elf files can be generated by the %.elf rule (which here looks like you've broken the pattern, as there's no % in the dependencies).
There's no rule for .o in this file, so the default recipe $(CC) $(CPPFLAGS) $(CFLAGS) -c is used. Since a .c file is found, this rule is applicable and generates the first command. The rule could have been written (as shown in suffix rules):
.c.o:
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $# $<
Backtrack up this list, now that the source has been found, and run the commands.
If the implicit rule variables are left unset, you will typically get programs built for your host system using cc.

Makefile C Ubuntu - Having problems [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I have 3 files: MyLib.h MyLib.c Tester.c
I've been trying to create the makefile but it is proving difficult.
I can do it when it is only one file, like below where I am compiling Hello.c
I have seen some examples but they seem a lot more complicated than the one I am using below -- which sort of makes sense to me.
BINDIR = /usr/local/sbin
CC = gcc
CFLAGS = -O
all: Hello
Hello: Hello.o
${CC} ${CFLAGS} Hello.o ${LDFLAGS} -o Hello
Hello.o: Hello.c
${CC} ${CFLAGS} -c Hello.c
install: all
rm -f ${BINDIR}/Hello
cp Hello ${BINDIR}/Hello
clean:
rm -f Hello *.o core core.* *.core
Please help.
I been typing this every time I turn on my computer, kind of annoying by now.
gcc MyLib.c Tester.c -o Tester
Presuming MyLib.h is a dependency for both of your C files, you should have something like this:
# Variables
CC := gcc
CFLAGS := -O
# Link executable
Tester: MyLib.o Tester.o
${CC} MyLib.o Tester.o ${LDFLAGS} -o Tester
# Compile object files
MyLib.o: MyLib.c MyLib.h
${CC} ${CFLAGS} -c -o MyLib.o MyLib.c
Tester.o: Tester.c MyLib.h
${CC} ${CFLAGS} -c -o Tester.o Tester.c
and, once you've got the hang of how things work, you can use the automatic variables as your second step in reducing code duplication:
# Variables
CC := gcc
CFLAGS := -O
# Link executable
Tester: MyLib.o Tester.o
${CC} $^ ${LDFLAGS} -o $#
# Compile object files
MyLib.o: MyLib.c MyLib.h
${CC} ${CFLAGS} -c -o $# $<
Tester.o: Tester.c MyLib.h
${CC} ${CFLAGS} -c -o $# $<
where $# is the replaced by the name of the target for the current rule, $< is replaced by the first (i.e. leftmost) dependency, and $^ is replaced by the full list of dependencies.
In the above, the bits after the : are dependencies, i.e. the target to the left of the : will be made/remade if any of the dependencies are more recent than the target. For each of the dependencies, make will look for a target for it. So, for the first section, it sees that MyLib.o and Tester.o are dependencies for your overall executable, and it looks for targets for them, which are provided. Finding the targets, it builds them (if necessary) and then proceeds to build Tester.
Note that CFLAGS conventionally represents compilation flags, so you don't need to pass them when you're only linking since no compilation is being done at that point.
Also, if you're struggling with this kind of thing, then simplify, and remove all the additional targets (such as clean and install and all) until you've got the hang of what's going on.
Crude but effective:
Tester:
gcc MyLib.c Tester.c -o Tester
Better:
CC = gcc
Tester: MyLib.o Tester.o
$(CC) $^ -o $#
And I'll just make a guess about dependency:
MyLib.o Tester.o : MyLib.h
More sophisticated makefiles are possible, but this should do for now.

makefile which get also the name of the file compile

I need a makefile which get also the name of the file compile
For example:
make foo
and the makefile should compile foo.c to foo.
This is my makefile. How to change it?
all: out
out: out.o
gcc -g -m32 -Wall -o out out.o
out.o: out.c
gcc -m32 -g -Wall -ansi -c -o out.o out.c
.PHONY: clean
#Clean the build directory
clean:
rm -f *.o out
There is no direct way where you can pass arguments to the Makefile but instead you can take advantage of variables to achieve what you want. Check the modifications done to the Makefile below
NAME ?=out #Default binary generated is out if you dont pass any argument
${NAME}: ${NAME}.o
gcc -g -m32 -Wall -o ${NAME} ${NAME}.o
${NAME}.o: ${NAME}.c
gcc -m32 -g -Wall -ansi -c -o ${NAME}.o out.c
.PHONY: clean
#Clean the build directory
clean:
`rm -f *.o ${NAME}`
And you should call the Makefile by typing
$ make NAME=foo
$ make clean NAME=foo
Passing arguments directly to Make is trivially easy.
Your current makefile can be invoked with make foo, and will compile foo.c to produce foo, because Make has implicit rules for handling cases like foo.c => foo; there will be no error even though "foo" is not the target of any rule. (At least, this is the case with GNU Make 3.81, which is what I am using.)
If you want to control the choice of compiler and flags (as in your out rule), there is more than one way to do it. The simplest (though not strictly the best) is to modify a couple of variables in the makefile:
CC = gcc
CFLAGS = -g -m32 -Wall -ansi
Another option is to override the implicit rule with a pattern rule of your own:
%: %.c
gcc -g -m32 -Wall -ansi -o $# $<
If you want it to build foo.o in a separate step, you must split the rule into two rule-- and also put in a rule with no recipe to cancel Make's implicit rule:
%: %.o
gcc -g -m32 -Wall -o $# $^
%.o: %.c
gcc -m32 -g -Wall -ansi -c -o $# $<
%: %.c
Further refinements are possible, once you have mastered the basics.

How to define rules in the Makefile to compile only that *.cpp files which was modified (and their dependencies), not all *.cpp files

Lets say I have files:
Libs:
one.cpp, one.h
two.cpp, two.h
three.cpp, three.h
Program:
program.cpp
Is there way, to create Makefile which will compile only that *.cpp which were modified from last compilation?
Currently I have something like that:
SRCS = one.cpp two.cpp three.cpp
OBJS = $(SRCS:.cpp=.o)
all: $(OBJS) program
.cpp.o:
g++ -Wall -c $<
program:
g++ -Wall $(OBJS) program.cpp -o program
clean:
rm -f $(OBJS) program
I works fine, but when I compile my program and then change two.cpp or two.h I need to run "make clean" first, because when I secondly run "make" I get:
Nothing to be done for 'all'.
I would like to change my Makefile in that way, it would recognize my changes and recompile that file and its dependencies (if one.cpp uses code from two.cpp which was modified, both files should be recompiled).
So if I modify two.cpp, make should do:
g++ -Wall -c two.cpp
g++ -Wall $(OBJS) program.cpp -o program
But if one.cpp uses code from two.cpp which was modified, make shold do:
g++ -Wall -c one.cpp
g++ -Wall -c two.cpp
g++ -Wall $(OBJS) program.cpp -o program
First we make the object files prerequisites of the executable. Once this is done, Make will rebuild program whenever one of the SRCS changes, so we don't need OBJS as an explicit target:
all: program
program: $(OBJS)
g++ -Wall $(OBJS) program.cpp -o program
Then we make the header files prerequisites of the objects, so that if we change three.h, Make will rebuild three.o:
$(OBJS): %.o : %.h
And finally since one.cpp uses code from two.cpp by means of two.h (I hope), we make two.h a prerequisite of one.o:
one.o: two.h
And to make things cleaner and easier to maintain we use automatic variables:
program: $(OBJS)
g++ -Wall $^ program.cpp -o $#
Put it all together and we get:
SRCS = one.cpp two.cpp three.cpp
OBJS = $(SRCS:.cpp=.o)
all: program
$(OBJS): %.o : %.h
one.o: two.h
.cpp.o:
g++ -Wall -c $<
program: $(OBJS)
g++ -Wall $^ program.cpp -o $#
clean:
rm -f $(OBJS) program
There are a few more things we could do (like adding program.o to OBJS), but this is enough for today.
Add the files a command depends upon to run to the right of the target name.
Example:
default: hello.c
gcc -o hello.bin hello.c
install: hello.bin
cp hello.bin ../
All you need to do is tell make that the .o file depends on the .cpp file:
%.cpp.o: %.cpp
g++ -Wall -c -o $# $<

Resources