Linux(程序设计):17---通用型Makefile设计案例

目的需求

  • 在目录下有一系列的.c文件,我们需要用这些.c文件进行链接,然后生成一个名为“helloworld”
  • 针对需要生成的目标文件,我们会一步一步的对Makefile进行设计,最终形成一个通用型的Makefile

一、Makefile-1设计

helloworld:cerrexit.o connectsock.o connectTCP.o connectUDP.o dcon.o do_echo.o do_noga.o do_notsup.o do_txbinary.o errexit.o fsmbuild.o fsminit.o \
passivesock.o recopt.o scrgetc.o scrinit.o scrwrap.o sofsm.o sonotsup.o soputc.o sowrite.o status.o subend.o \
subfsm.o subopt.o subtermtype.o suspend.o sync.o tclient.o tcout.o telnet.o tnabort.o ttfsm.o ttputc.o ttwrite.o \
ttysetup.o unscript.o will_notsup.o will_termtype.o will_txbinary.o xput.o
	gcc cerrexit.o connectsock.o connectTCP.o connectUDP.o dcon.o do_echo.o do_noga.o do_notsup.o do_txbinary.o errexit.o fsmbuild.o fsminit.o \
passivesock.o recopt.o scrgetc.o scrinit.o scrwrap.o sofsm.o sonotsup.o soputc.o sowrite.o status.o subend.o \
subfsm.o subopt.o subtermtype.o suspend.o sync.o tclient.o tcout.o telnet.o tnabort.o ttfsm.o ttputc.o ttwrite.o \
ttysetup.o unscript.o will_notsup.o will_termtype.o will_txbinary.o xput.o -o helloword	

cerrexit.o:cerrexit.c
	gcc -c  cerrexit.c -o cerrexit.o
connectsock.o:connectsock.c
	gcc -c  connectsock.c -o connectsock.o
connectTCP.o:connectTCP.c
	gcc -c  connectTCP.c -o connectTCP.o
connectUDP.o:connectUDP.c
	gcc -c  connectUDP.c -o connectUDP.o
dcon.o:dcon.c
	gcc -c  dcon.c -o dcon.o
do_echo.o:do_echo.c
	gcc -c  do_echo.c -o do_echo.o
do_noga.o:do_noga.c
	gcc -c  do_noga.c -o do_noga.o
do_notsup.o:do_notsup.c
	gcc -c  do_notsup.c -o do_notsup.o
do_txbinary.o:do_txbinary.c
	gcc -c  do_txbinary.c -o do_txbinary.o
errexit.o:errexit.c
	gcc -c  errexit.c -o errexit.o
fsmbuild.o:fsmbuild.c
	gcc -c  fsmbuild.c -o fsmbuild.o
fsminit.o:fsminit.c
	gcc -c  fsminit.c -o fsminit.o
passivesock.o:passivesock.c
	gcc -c  passivesock.c -o passivesock.o
recopt.o:recopt.c
	gcc -c  recopt.c -o recopt.o
scrgetc.o:scrgetc.c
	gcc -c  scrgetc.c -o scrgetc.o
scrinit.o:scrinit.c
	gcc -c  scrinit.c -o scrinit.o
scrwrap.o:scrwrap.c
	gcc -c  scrwrap.c -o scrwrap.o
sofsm.o:sofsm.c
	gcc -c  sofsm.c -o sofsm.o
sonotsup.o:sonotsup.c
	gcc -c  sonotsup.c -o sonotsup.o
soputc.o:soputc.c
	gcc -c  soputc.c -o soputc.o
sowrite.o:sowrite.c
	gcc -c  sowrite.c -o sowrite.o
status.o:status.c
	gcc -c  status.c -o status.o
subend.o:subend.c
	gcc -c  subend.c -o subend.o
subfsm.o:subfsm.c
	gcc -c  subfsm.c -o subfsm.o
subopt.o:subopt.c
	gcc -c  subopt.c -o subopt.o
subtermtype.o:subtermtype.c
	gcc -c  subtermtype.c -o subtermtype.o
suspend.o:suspend.c
	gcc -c  suspend.c -o suspend.o
sync.o:sync.c
	gcc -c  sync.c -o sync.o
tclient.o:tclient.c
	gcc -c  tclient.c -o tclient.o
tcout.o:tcout.c
	gcc -c  tcout.c -o tcout.o
telnet.o:telnet.c
	gcc -c  telnet.c -o telnet.o
tnabort.o:tnabort.c
	gcc -c  tnabort.c -o tnabort.o
ttfsm.o:ttfsm.c
	gcc -c  ttfsm.c -o ttfsm.o
ttputc.o:ttputc.c
	gcc -c  ttputc.c -o ttputc.o
ttwrite.o:ttwrite.c
	gcc -c  ttwrite.c -o ttwrite.o
ttysetup.o:ttysetup.c
	gcc -c  ttysetup.c -o ttysetup.o
unscript.o:unscript.c
	gcc -c  unscript.c -o unscript.o
will_notsup.o:will_notsup.c
	gcc -c  will_notsup.c -o will_notsup.o
will_termtype.o:will_termtype.c
	gcc -c  will_termtype.c -o will_termtype.o
will_txbinary.o:will_txbinary.c
	gcc -c  will_txbinary.c -o will_txbinary.o
xput.o:xput.c
	gcc -c  xput.c -o xput.o


.PHONY:
clean:
	rm -rf *.o helloworld

脚本解释

  • 使用gcc命令逐个生成每个.c文件对应的.o文件
  • 将所有的.o文件生成之后,使用gcc命令将其作为依赖文件,生成目标文件helloworld
  • clean伪目标:删除所有.o文件与目标文件

执行结果

Linux(程序设计):17---通用型Makefile设计案例_第1张图片Linux(程序设计):17---通用型Makefile设计案例_第2张图片

二、Makefile-2设计

#object变量采用:=赋值,当后面有其他.o文件需要加进来时,可以对object+=赋值
object := cerrexit.o connectsock.o connectTCP.o connectUDP.o dcon.o do_echo.o do_noga.o do_notsup.o do_txbinary.o errexit.o fsmbuild.o fsminit.o \
passivesock.o recopt.o scrgetc.o scrinit.o scrwrap.o sofsm.o sonotsup.o soputc.o sowrite.o status.o subend.o \
subfsm.o subopt.o subtermtype.o suspend.o sync.o tclient.o tcout.o telnet.o tnabort.o ttfsm.o ttputc.o ttwrite.o \
ttysetup.o unscript.o will_notsup.o will_termtype.o will_txbinary.o xput.o

#代表使用的编译器,例如本次使用的是gcc,使用其它编译器时,只需更改此选项即可
CC = gcc
FLAG = -c

parameter_o=-o
target=helloworld

$(target):$(object)
	$(CC) $(object) $(parameter_o) $(target)

cerrexit.o:cerrexit.c
	$(CC) $(FLAG)  cerrexit.c $(parameter_o) cerrexit.o
connectsock.o:connectsock.c
	$(CC) $(FLAG)  connectsock.c $(parameter_o) connectsock.o
connectTCP.o:connectTCP.c
	$(CC) $(FLAG)  connectTCP.c $(parameter_o) connectTCP.o
connectUDP.o:connectUDP.c
	$(CC) $(FLAG)  connectUDP.c $(parameter_o) connectUDP.o
dcon.o:dcon.c
	$(CC) $(FLAG)  dcon.c $(parameter_o) dcon.o
do_echo.o:do_echo.c
	$(CC) $(FLAG)  do_echo.c $(parameter_o) do_echo.o
do_noga.o:do_noga.c
	$(CC) $(FLAG)  do_noga.c $(parameter_o) do_noga.o
do_notsup.o:do_notsup.c
	$(CC) $(FLAG)  do_notsup.c $(parameter_o) do_notsup.o
do_txbinary.o:do_txbinary.c
	$(CC) $(FLAG)  do_txbinary.c $(parameter_o) do_txbinary.o
errexit.o:errexit.c
	$(CC) $(FLAG)  errexit.c $(parameter_o) errexit.o
fsmbuild.o:fsmbuild.c
	$(CC) $(FLAG)  fsmbuild.c $(parameter_o) fsmbuild.o
fsminit.o:fsminit.c
	$(CC) $(FLAG)  fsminit.c $(parameter_o) fsminit.o
passivesock.o:passivesock.c
	$(CC) $(FLAG)  passivesock.c $(parameter_o) passivesock.o
recopt.o:recopt.c
	$(CC) $(FLAG)  recopt.c $(parameter_o) recopt.o
scrgetc.o:scrgetc.c
	$(CC) $(FLAG)  scrgetc.c $(parameter_o) scrgetc.o
scrinit.o:scrinit.c
	$(CC) $(FLAG)  scrinit.c $(parameter_o) scrinit.o
scrwrap.o:scrwrap.c
	$(CC) $(FLAG)  scrwrap.c $(parameter_o) scrwrap.o
sofsm.o:sofsm.c
	$(CC) $(FLAG)  sofsm.c $(parameter_o) sofsm.o
sonotsup.o:sonotsup.c
	$(CC) $(FLAG)  sonotsup.c $(parameter_o) sonotsup.o
soputc.o:soputc.c
	$(CC) $(FLAG)  soputc.c $(parameter_o) soputc.o
sowrite.o:sowrite.c
	$(CC) $(FLAG)  sowrite.c $(parameter_o) sowrite.o
status.o:status.c
	$(CC) $(FLAG)  status.c $(parameter_o) status.o
subend.o:subend.c
	$(CC) $(FLAG)  subend.c $(parameter_o) subend.o
subfsm.o:subfsm.c
	$(CC) $(FLAG)  subfsm.c $(parameter_o) subfsm.o
subopt.o:subopt.c
	$(CC) $(FLAG)  subopt.c $(parameter_o) subopt.o
subtermtype.o:subtermtype.c
	$(CC) $(FLAG)  subtermtype.c $(parameter_o) subtermtype.o
suspend.o:suspend.c
	$(CC) $(FLAG)  suspend.c $(parameter_o) suspend.o
sync.o:sync.c
	$(CC) $(FLAG)  sync.c $(parameter_o) sync.o
tclient.o:tclient.c
	$(CC) $(FLAG)  tclient.c $(parameter_o) tclient.o
tcout.o:tcout.c
	$(CC) $(FLAG)  tcout.c $(parameter_o) tcout.o
telnet.o:telnet.c
	$(CC) $(FLAG)  telnet.c $(parameter_o) telnet.o
tnabort.o:tnabort.c
	$(CC) $(FLAG)  tnabort.c $(parameter_o) tnabort.o
ttfsm.o:ttfsm.c
	$(CC) $(FLAG)  ttfsm.c $(parameter_o) ttfsm.o
ttputc.o:ttputc.c
	$(CC) $(FLAG)  ttputc.c $(parameter_o) ttputc.o
ttwrite.o:ttwrite.c
	$(CC) $(FLAG)  ttwrite.c $(parameter_o) ttwrite.o
ttysetup.o:ttysetup.c
	$(CC) $(FLAG)  ttysetup.c $(parameter_o) ttysetup.o
unscript.o:unscript.c
	$(CC) $(FLAG)  unscript.c $(parameter_o) unscript.o
will_notsup.o:will_notsup.c
	$(CC) $(FLAG)  will_notsup.c $(parameter_o) will_notsup.o
will_termtype.o:will_termtype.c
	$(CC) $(FLAG)  will_termtype.c $(parameter_o) will_termtype.o
will_txbinary.o:will_txbinary.c
	$(CC) $(FLAG)  will_txbinary.c $(parameter_o) will_txbinary.o
xput.o:xput.c
	$(CC) $(FLAG)  xput.c $(parameter_o) xput.o


.PHONY:
clean:
	rm -rf *.o  $(target)

脚本解释

  • 针对于Makefile-1,我们使用了Makefile中变量的概念
  • object变量需要增加内容时,可以object += exp.o

执行结果

Linux(程序设计):17---通用型Makefile设计案例_第3张图片Linux(程序设计):17---通用型Makefile设计案例_第4张图片

三、Makefile-3设计

#object变量采用:=赋值,当后面有其他.o文件需要加进来时,可以对object+=赋值
object := cerrexit.o connectsock.o connectTCP.o connectUDP.o dcon.o do_echo.o do_noga.o do_notsup.o do_txbinary.o errexit.o fsmbuild.o fsminit.o \
passivesock.o recopt.o scrgetc.o scrinit.o scrwrap.o sofsm.o sonotsup.o soputc.o sowrite.o status.o subend.o \
subfsm.o subopt.o subtermtype.o suspend.o sync.o tclient.o tcout.o telnet.o tnabort.o ttfsm.o ttputc.o ttwrite.o \
ttysetup.o unscript.o will_notsup.o will_termtype.o will_txbinary.o xput.o

#代表使用的编译器,例如本次使用的是gcc,使用其它编译器时,只需更改此选项即可
CC = gcc
FLAG = -c

parameter_o=-o
target=helloworld

#“$^”代表依赖文件,“$@”代表目标文件
$(target):$(object)
	$(CC) $^ $(parameter_o) $@

cerrexit.o:cerrexit.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
connectsock.o:connectsock.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
connectTCP.o:connectTCP.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
connectUDP.o:connectUDP.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
dcon.o:dcon.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
do_echo.o:do_echo.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
do_noga.o:do_noga.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
do_notsup.o:do_notsup.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
do_txbinary.o:do_txbinary.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
errexit.o:errexit.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
fsmbuild.o:fsmbuild.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
fsminit.o:fsminit.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
passivesock.o:passivesock.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
recopt.o:recopt.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
scrgetc.o:scrgetc.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
scrinit.o:scrinit.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
scrwrap.o:scrwrap.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
sofsm.o:sofsm.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
sonotsup.o:sonotsup.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
soputc.o:soputc.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
sowrite.o:sowrite.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
status.o:status.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
subend.o:subend.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
subfsm.o:subfsm.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
subopt.o:subopt.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
subtermtype.o:subtermtype.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
suspend.o:suspend.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
sync.o:sync.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
tclient.o:tclient.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
tcout.o:tcout.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
telnet.o:telnet.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
tnabort.o:tnabort.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
ttfsm.o:ttfsm.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
ttputc.o:ttputc.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
ttwrite.o:ttwrite.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
ttysetup.o:ttysetup.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
unscript.o:unscript.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
will_notsup.o:will_notsup.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
will_termtype.o:will_termtype.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
will_txbinary.o:will_txbinary.c
	$(CC) $(FLAG) $^ $(parameter_o) $@
xput.o:xput.c
	$(CC) $(FLAG) $^ $(parameter_o) $@


.PHONY:
clean:
	rm -rf *.o  $(target)

脚本解释

此处我们使用了Makefile中自动变量的概念,所以我们将Makefile中所有gcc命令的依赖文件和目标文件分别用“$^“,“$@”代替

  • $^:代表依赖文件
  • $@:代表目标文件

执行结果

Linux(程序设计):17---通用型Makefile设计案例_第5张图片Linux(程序设计):17---通用型Makefile设计案例_第6张图片

四、Makefile-4设计

object:=cerrexit.o connectsock.o connectTCP.o connectUDP.o dcon.o do_echo.o do_noga.o do_notsup.o do_txbinary.o errexit.o fsmbuild.o fsminit.o \
passivesock.o recopt.o scrgetc.o scrinit.o scrwrap.o sofsm.o sonotsup.o soputc.o sowrite.o status.o subend.o \
subfsm.o subopt.o subtermtype.o suspend.o sync.o tclient.o tcout.o telnet.o tnabort.o ttfsm.o ttputc.o ttwrite.o \
ttysetup.o unscript.o will_notsup.o will_termtype.o will_txbinary.o xput.o

CC=gcc
FLAG = -c
parameter_o=-o
target=helloword

$(target):$(object)
	$(CC) $^  $(parameter_o) $@

%.o:%.c
	$(CC) $(FLAG)  $^  $(parameter_o) $@

.PHONY:
clean:
	rm -rf $(object) $(target)

脚本解释

  • 利用Makefile的隐式规则:我们需要用任意一个.c文件来生成.o文件,并且Makefile利用隐式规则会自动匹配来用.c文件来生成.o文件,因此我们可以将一系列复杂的gcc命令缩减为一句话

  • %通配符:任意一个

执行结果

Linux(程序设计):17---通用型Makefile设计案例_第7张图片Linux(程序设计):17---通用型Makefile设计案例_第8张图片

五、Makefile-5设计

object:=cerrexit.o connectsock.o connectTCP.o connectUDP.o dcon.o do_echo.o do_noga.o do_notsup.o do_txbinary.o errexit.o fsmbuild.o fsminit.o \
passivesock.o recopt.o scrgetc.o scrinit.o scrwrap.o sofsm.o sonotsup.o soputc.o sowrite.o status.o subend.o \
subfsm.o subopt.o subtermtype.o suspend.o sync.o tclient.o tcout.o telnet.o tnabort.o ttfsm.o ttputc.o ttwrite.o \
ttysetup.o unscript.o will_notsup.o will_termtype.o will_txbinary.o xput.o

CC=gcc
FLAG = -g
parameter_o=-o
LIB = -ltermcap     #-L/work/mylib/printf.so加入绝对路径的方法
DEFS = -DEBUG       #宏定义
INCLUDE=
target=helloword

$(target):$(object)
	$(CC) $(FLAG) $^  $(parameter_o) $@  $(LIB)

.PHONY:
clean:
	rm -rf $(object) $(target)

脚本解释

  • 利用Makefile的隐式规则:我们可以直接将下面这句话删除了,因为系统会自动生成

 

执行结果

Linux(程序设计):17---通用型Makefile设计案例_第9张图片Linux(程序设计):17---通用型Makefile设计案例_第10张图片

六、Makefile-6设计

#$(函数名  函数的参数)
SRC=$(wildcard *.c)  #wildcard提取当前目录下的所有.c文件的名称,SRC是这些所有.c文件的字符串列表
OBJS=$(patsubst %.c,%.o,$(SRC)) #patsubst字符串转换函数,将SRC中的所有.c字符串变为.o字符串

CC=gcc
FLAG = -g
parameter_o=-o
LIB = -ltermcap
DEFS=-DEBUG
INCLUDE=
target=helloword

$(target):$(object)
	$(CC)  $^  $(parameter_o) $@  $(LIB)

.PHONY:
clean:
	rm -rf $(object) $(target)

脚本解释

  • wildcard函数:提取当前目录下的所有.c文件的名称,SRC是这些所有.c文件的字符串列表
  • patsubst函数:字符串转换函数,将SRC中的所有.c字符串变为.o字符串

原理:

  • 我们先用wildcard函数获取所有的.c文件字符串列表保存在SRC中
  • 然后使用patsubst函数,将SRC中所有的.c文件变为.o文件,保存为OBJS,然后用这个OBJS作为依赖文件生成目标文件

执行结果

Linux(程序设计):17---通用型Makefile设计案例_第11张图片Linux(程序设计):17---通用型Makefile设计案例_第12张图片

总结

  • Makefile-6作为我们最终的Makefile来使用,也是最简洁的

你可能感兴趣的:(Linux(程序设计))