How dependencies works on gnu Makefile ?
I want to create a Makefile which:
- will apply some patches (in our exmaple, apply main.patch on main.c)
- create a programm called toto from patched main.c file
my_patch=./main.patch
all: toto
patch: $(my_patch)
echo "apply patch"
main.o: main.c
gcc -o main.o -c main.c -Wall
toto: patch main.o $(my_patch)
echo "build"
gcc -o toto main.o
but, the patch are always applied ... which leads me on my question:
"How dependencies works on gnu Makefile ?"
How can I tell to gnu make that it's useless to apply main.patch if the date of main.patch is smaller than the binary toto
thanks for any help :)
The phony target (patch) is confusing things. The patch rule modifies main.c, so let that be the target:
my_patch=./main.patch
all: toto
main.c: $(my_patch)
echo "apply patch"
main.o: main.c
gcc -o main.o -c main.c -Wall
toto: main.o # no need to specify $(my_patch) here
echo "build"
gcc -o toto main.o
P.S. while you're at it, you may as well introduce automatic variables; the makefile is cleaner and easier to maintain that way:
main.o: main.c
gcc -o $# -c $< -Wall
toto: main.o # no need to specify $(my_patch) here
echo "build"
gcc -o $# $^
Related
I'm trying to create a makefile titled 'p1' for a project.
When I try the command make p1 it returns with make: nothing to be done for p1
Also, when I try the command make p1 clean it returns no rule to make p1 'clean.' Stop
Here is my makefile:
a.out: main.o P1LinkedList.o const_iterator.o iterator.o Node.o
g++ -std=c++11 main.o const_iterator.o iterator.o Node.o
main.o:
g++ -std=c++11 -c main.cpp
P1LinkedList.o:
g++ -std=c++11 -c P1LinkedList.cpp
iterator.o:
g++ -std=c++11 -c iterator.cpp
const_iterator.o:
g++ -std=c++11 -c const_iterator.cpp
Node.o:
g++ -std=c++11 -c Node.cpp
depend:
g++ -MM main.cpp > p1.dep
clean:
rm -f a.out *.o
What do I need to fix to have the makefile compile .o files from my .cpp files and how do I fix the issue with the clean command?
Edit:
Here are the commands I've used to compile manually:
Helens-Air:p1a helenade$ g++ -std=c++11 *.cpp
Helens-Air:p1a helenade$ ./a.out
^^ and this just continues with the program execution from there
We may have to take this in stages.
First, you seem to misunderstand the difference between a makefile name and a target name. This appears to have been a miscommunication between you and your teacher, but it's easy to clear up.
Suppose you have a makefile named "Makefile", containing the following:
foo:
#echo running the foo rule
bar:
#echo running the bar rule
If you make foo, you will get:
running the foo rule
The argument (foo) tells Make which target to attempt to build. And how did Make know which makefile to use? (After all, you could have a dozen makefiles in the working directory.) You can specify which makefile to use, but if you don't then by default Make will look for a makefile named Makefile (or makefile or GNUmakefile, don't worry about this for now). To specify a makefile with another name, like "Buildfile", you can use the -f flag:
make -f Buildfile
So "p1" ought to have been the name of a target, not a makefile. Within the makefile, rename your a.out rule to p1. Then rename the whole makefile to Makefile. Then
make p1
should work (or at least run).
Edit:
I'll go out on a limb. In the a.out rule (which should now be called the p1 rule), I notice that you have left P1LinkedList.o out of the list of object files to be linked. So try changing it:
p1: main.o P1LinkedList.o const_iterator.o iterator.o Node.o
g++ -std=c++11 main.o P1LinkedList.o const_iterator.o iterator.o Node.o
If that works, you can simplify it with an automatic variable:
p1: main.o P1LinkedList.o const_iterator.o iterator.o Node.o
g++ -std=c++11 $^
And there will be other small improvements you can make.
If it doesn't work, try ls *.cpp and see if you've overlooked some other source file.
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.
I have this very basic makefile:
CC=gcc
CFLAGS=-Wall -g -O -pedantic -Wformat=2 -Wextra -lm
And actually it compile foo.c to foo. How can I add a custom extension, for example I want it to compile foo.c in foo.run.
Thank you very much.
Add this to your makefile:
foo.run : foo.c
$(CC) $(CFLAGS) -o $# $<
Make sure the second line starts with a tab character, not spaces. Then check out the manual page or other documentation for your version of make.
I have main.cpp (including main function) and func1.cpp, and I want to link these files with a makefile. Classic form would be:
main: main.o func1.o
g++ main.o func1.o -o main
main.o: main.cpp
g++ -c main.cpp
func1.o: func1.cpp
g++ -c func1.cpp
or one can write
main: func1.o main.o
g++ main.o func1.o -o main
func1.o: func1.cpp
g++ -c func1.cpp
main.o: main.cpp
g++ -c main.cpp
or
main: main.o func1.o
g++ main.o func1.o -o main
func1.o: func1.cpp
g++ -c func1.cpp
main.o: main.cpp
g++ -c main.cpp
Do the last two differ from the classic one ? Does one have some advantages over the other?
No, the only time the order of the rules comes into play is when you just enter make, in which case it can choose the first rule as the default.
Beyond that, make is intelligent enough to execute dependent rules no matter where they are in the file.
There is no difference between the three sets of ruls. However, make knows how build .cpp files into object files, so all you really need is:
main: main.o func1.o
g++ main.o func1.o -o $#
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 $# $<