[SOLVED] CS ECS 150 Makefile tutorial

$25

File Name: CS_ECS_150__Makefile_tutorial.zip
File Size: 273.18 KB

5/5 - (1 vote)

ECS 150 Makefile tutorial
Prof. Joel Porquet-Lupine
UC Davis 2020/2021
Copyright 2017-2021 Joel Porquet-Lupine CC BY-NC-SA 4.0 International License /
1 / 22

Manual approach
Code example
main.c fact.h
#include #include
#include fact.h
int main(int argc, char **argv)
{
int n;
if (argc < 2) { fprintf(stderr,”Usage: myfact number
“);exit(1);}n = atoi(argv[1]);printf(“fact(%d) = %d
“,n, fact(n)); return 0;}main.c #ifndef FACT_H_ #define FACT_H_int fact(int n); #endif /* FACT_H_ */fact.hfact.c#include “fact.h”int fact(int n) { if (n == 0)return 1;return n * fact(n – 1);}fact.cREADME.md# OverviewThis program computes thefactorial of a numberREADME.md2 / 22/ Manual approachCompilation$ gcc -Wall -Wextra -Werror -c -o fact.o fact.c$ gcc -Wall -Wextra -Werror -c -o main.o main.c$ gcc -Wall -Wextra -Werror -o myfact main.o fact.o $ ./myfactUsage: myfact number $ ./myfact 5 fact(5) = 120 $ pandoc -o README.html README.md $ firefox README.htmlOn the long run…Now, what if:fact.c changes? main.c changes? fact.h changes?I want to change the compilation options?I want to recompile this code on another computer? I want to share this code?Solution is to automate the build process!3 / 22/ IntroductionDefinitionA Makefile is a file containing a set of rules used with the make build automation tool. The two following commands are equivalent:$ lsMakefile …$ make$ make -f MakefileThe set of Makefile rules usually represents the various steps to follow in order to build a program: it’s the building recipe.4 / 22/ IntroductionAnatomy of a ruleFor target to be generated, the prerequisites must all exists (or be generated if necessary)is generated by executing the specified commandis generated only if it does not exist, or if one of the prerequisites is morerecentPrevents from building everything each time, but only what is necessaryCommentingLines prefixed with # are not evaluated # This is a commenttarget: [list of prerequisites][ command ]
target
target
5 / 22
/

Version 0.1
Basic rules
myfact: main.o fact.o
gcc -Wall -Wextra -Werror -o myfact main.o fact.o
main.o: main.c fact.h
gcc -Wall -Wextra -Werror -c -o main.o main.c
fact.o: fact.c fact.h
gcc -Wall -Wextra -Werror -c -o fact.o fact.c
README.html: README.md
pandoc -o README.html README.md
Makefile_v0.1
$ make
gcc -c -o main.o main.c gcc -c -o fact.o fact.c gcc -o myfact main.o fact.o
$ make README.html
pandoc -o README.html README.md
6 / 22
/

Version 0.1
all rule
all: myfact README.html
myfact: main.o fact.o
gcc -Wall -Wextra -Werror -o myfact main.o fact.o
main.o: main.c fact.h
gcc -Wall -Wextra -Werror -c -o main.o main.c
fact.o: fact.c fact.h
gcc -Wall -Wextra -Werror -c -o fact.o fact.c
README.html: README.md
pandoc -o README.html README.md
Makefile_v0.1
$ make
gcc -c -o main.o main.c
gcc -c -o fact.o fact.c
gcc -o myfact main.o fact.o pandoc -o README.html README.md
7 / 22
/

Version 0.1
clean rule
all: myfact README.html

clean:
rm -f myfact README.html main.o fact.o
Makefile_v0.1
$ make
gcc -c -o main.o main.c
gcc -c -o fact.o fact.c
gcc -o myfact main.o fact.o pandoc -o README.html README.md
$ make clean
rm -f myfact README.html main.o fact.o
8 / 22
/

Version 0.1
A first and basic Makefile
all: myfact README.html
myfact: main.o fact.o
gcc -Wall -Wextra -Werror -o myfact main.o fact.o
main.o: main.c fact.h
gcc -Wall -Wextra -Werror -c -o main.o main.c
fact.o: fact.c fact.h
gcc -Wall -Wextra -Werror -c -o fact.o fact.c
README.html: README.md
pandoc -o README.html README.md
clean:
rm -f myfact README.html main.o fact.o
Makefile_v0.1
Was good enough for Project #1
(No need to generate html out of markdown pandoc is not installed on CSIF, and also its just for the example)
9 / 22
/

Version 1.0
How to avoid redundancy?
A good programmer is a lazy programmer!
all: myfact README.html
myfact: main.o fact.o
gcc -Wall -Wextra -Werror -o myfact main.o fact.o
main.o: main.c fact.h
gcc -Wall -Wextra -Werror -c -o main.o main.c
fact.o: fact.c fact.h
gcc -Wall -Wextra -Werror -c -o fact.o fact.c
README.html: README.md
pandoc -o README.html README.md
clean:
rm -f myfact README.html main.o fact.o
Makefile_v0.1
10 / 22
/

Version 1.0
Automatic variables in commands
: replaced by name of target
: replaced by name of first prerequisite : replaced by names of all prerequisites
$@
$< $^ all: myfact README.htmlmyfact: main.o fact.ogcc -Wall -Wextra -Werror -o $@ $^ main.o: main.c fact.hgcc -Wall -Wextra -Werror -c -o $@ $< fact.o: fact.c fact.hgcc -Wall -Wextra -Werror -c -o $@ $< README.html: README.mdpandoc -o $@ $<clean:rm -f myfact README.html main.o fact.o11 / 22/ Version 1.0Pattern rulesA pattern rule %.o: %.c says how to generate any file .o from another file . c.
all: myfact README.html
myfact: main.o fact.o
gcc -Wall -Wextra -Werror -o $@ $^ %.o: %.c fact.h
gcc -Wall -Wextra -Werror -c -o $@ $< %.html: %.mdpandoc -o $@ $<clean:rm -f myfact README.html main.o fact.o12 / 22/ Version 1.0Variables$ makegcc -Wall -Wextra -Werror -g -c -o main.o main.c gcc -Wall -Wextra -Werror -g -c -o fact.o fact.c gcc -Wall -Wextra -Werror -g -o myfact main.o fact.o pandoc -o README.html README.md CC:= gccCFLAGS:= -Wall -Wextra -WerrorCFLAGS+= -gPANDOC:= pandocall: myfact README.htmlmyfact: main.o fact.o$(CC) $(CFLAGS) -o $@ $^ %.o: %.c fact.h$(CC) $(CFLAGS) -c -o $@ $< %.html: %.md$(PANDOC) -o $@ $<clean:rm -f myfact README.html main.o fact.o13 / 22/ Version 2.0More variables$ makegcc -Wall -Wextra -Werror -g -c -o main.o main.c gcc -Wall -Wextra -Werror -g -c -o fact.o fact.c gcc -Wall -Wextra -Werror -g -o myfact main.o fact.o pandoc -o README.html README.md targets := myfact README.htmlobjs:= main.o fact.oCC:= gccCFLAGS:= -Wall -Wextra -WerrorCFLAGS+= -gPANDOC:= pandocall: $(targets)myfact: $(objs)$(CC) $(CFLAGS) -o $@ $^ %.o: %.c fact.h$(CC) $(CFLAGS) -c -o $@ $< %.html: %.md$(PANDOC) -o $@ $<clean:rm -f $(targets) $(objs)14 / 22/ Version 2.0Nice output$ makeCC main.oCC fact.oCC myfactMD README.html …myfact: $(objs) @echo “CC $@”@$(CC) $(CFLAGS) -o $@ $^%.o: %.c fact.h@echo “CC $@”@$(CC) $(CFLAGS) -c -o $@ $<%.html: %.md@echo “MD $@”@$(PANDOC) -o $@ $<clean:@echo “CLEAN”@rm -f $(targets) $(objs) $ make clean CLEANIn case of debug, how can we still see the commands that are executed? 15 / 22/ Version 3.0Conditional variables$ makeCC main.oCC fact.oCC myfactMD README.html …ifneq ($(V),1) Q=@endifmyfact: $(objs) @echo “CC $@”$(Q)$(CC) $(CFLAGS) -o $@ $^%.o: %.c fact.h@echo “CC $@”$(Q)$(CC) $(CFLAGS) -c -o $@ $<%.html: %.md@echo “MD $@”$(Q)$(PANDOC) -o $@ $<clean:@echo “CLEAN”$(Q)rm -f $(targets) $(objs) $ make V=1CC main.ogcc -Wall -Wextra -Werror -g -c -o main.o main.cCC fact.ogcc -Wall -Wextra -Werror -g -c -o fact.o fact.cCC myfactgcc -Wall -Wextra -Werror -g -o myfact main.o fact.o MD README.htmlpandoc -o README.html README.md16 / 22/ Version 3.0Generic rules vs dependency tracking Non-generic ruleGeneric rule%.o: %.c fact.h@echo “CC $@”$(Q)$(CC) $(CFLAGS) -c -o $@ $< $ makeCC main.oCC fact.oCC myfactMD README.html %.o: %.c@echo “CC $@”$(Q)$(CC) $(CFLAGS) -c -o $@ $M #include fact.h
int fact(int n) { if (n == 0)
return 1;
return n * fact(n 1);
}
$ gcc -Wall -Wextra -Werror -MMD -c -o fact.o fact.c
$ cat fact.d
fact.o: fact.c fact.h
19 / 22
/

Version 3.0
Dependency tracking Makefile integration
targets := myfact README.html
objs:= main.o fact.o

CFLAGS:= -Wall -Wextra -Werror -MMD

all: $(targets)
# Dep tracking *must* be below the all rule
deps := $(patsubst %.o,%.d,$(objs)) -include $(deps)

%.o: %.c
@echo CC $@
$(Q)$(CC) $(CFLAGS) -c -o $@ $<…clean:@echo “clean”$(Q)rm -f $(targets) $(objs) $(deps)Makefile_v3.0$(deps) will be computed from $(obj) into main.d fact.d Prefix – ignores inclusion errors20 / 22/ Version 3.0First runDependency files don’t exist but make won’t complainGCC generates them$ ls *.dFollowing runsDependency files are included by the MakefileThey are used to compose the generic rule for object generation $ makemake: Nothing to be done for ‘all’ $ touch fact.h$ makeCC main.oCC fact.oCC myfact $ makeCC main.oCC fact.oCC myfactMD README.html $ ls *.d main.d fact.d $ cat main.dmain.o: main.c fact.h $ cat fact.dfact.o: fact.c fact.h21 / 22/ Final Makefiletargets := myfact README.htmlobjs:= main.o fact.oCC:= gccCFLAGS:= -Wall -Wextra -Werror -MMDCFLAGS+= -gPANDOC:= pandocifneq ($(V),1) Q=@endifall: $(targets)# Dep tracking *must* be below the ‘all’ ruledeps := $(patsubst %.o,%.d,$(objs)) -include $(deps)myfact: $(objs) @echo “CC $@”$(Q)$(CC) $(CFLAGS) -o $@ $^%.o: %.c@echo “CC $@”$(Q)$(CC) $(CFLAGS) -c -o $@ $<%.html: %.md@echo “MD $@”$(Q)$(PANDOC) -o $@ $<clean:@echo “clean”$(Q)rm -f $(targets) $(objs) $(deps)Makefile_v3.022 / 22/

Reviews

There are no reviews yet.

Only logged in customers who have purchased this product may leave a review.

Shopping Cart
[SOLVED] CS ECS 150 Makefile tutorial
$25