[编译]Makefile兼APUE解析(UNP12)


本文内容:

- 最简单的Makefile知识点归纳,通过对apue-Makefile的内容,解剖出Makefile机制,并在此过程中,实践自己的algs4-hhc算法库工程(当然,是以学习Makefile为开始)
- 这编写过程中,为了方便本人复习,会适当提供参考资料,部分内容超出Makefile知识范围,自行跳过。

阅读人群:

- 读者没有任何编译原理知识,可以先去补充(推荐阅读《嵌入式linux开发教程 上册》10.1.3.2:gcc编译过程;这极其重要。
- 读者刚从windows转过来,一直使用IDE,也可以去补充。

apue.3e--Makefile解剖

  1. 顶层Makefile
DIRS = lib intro sockets advio daemons datafiles db environ \
    fileio filedir ipc1 ipc2 proc pty relation signals standards \
    stdio termios threadctl threads printer exercises

all:
    for i in $(DIRS); do \
        (cd $$i && echo "making $$i" && $(MAKE) ) || exit 1; \
    done

clean:
    for i in $(DIRS); do \
        (cd $$i && echo "cleaning $$i" && $(MAKE) clean) || exit 1; \
    done
 解析如下:
  1. 使用shell脚本的循环语句for,逐次进入各子目录里面执行make,并打印出making xxx。(其实该文件不算是一个Makefile,它更像是一个脚本,该脚本会在make的命令下执行,以便于提供子层make的环境)
  2. 而循环的次序也是有讲究的,所有的子层都会调用到libapue.a,所以第一个make的对象就是lib,接着可以随意。
  3. cd xxx || exit 1;意味着进入脚本目录,否则退出。在make过程中,会因为缺失某个目录而直接make error停止编译。链接,需要注意的是,这里使用到了逻辑或运算符,执行有先后顺序,前者为真则不需要之后后者。
  4. cd &&i,因为&是在Makefile中有特殊应用(自动变量),想执行shell命令,需要引用i,所以连续使用&符号。
参考链接:
shell--for循环写法, 链接

  1. 通用lib--Makefile
#
# Makefile for misc library.
#
ROOT=..
PLATFORM=$(shell $(ROOT)/systype.sh)
include $(ROOT)/Make.defines.$(PLATFORM)

LIBMISC    = libapue.a
OBJS   = bufargs.o cliconn.o clrfl.o \
            daemonize.o error.o errorlog.o lockreg.o locktest.o \
            openmax.o pathalloc.o popen.o prexit.o prmask.o \
            ptyfork.o ptyopen.o readn.o recvfd.o senderr.o sendfd.o \
            servaccept.o servlisten.o setfd.o setfl.o signal.o signalintr.o \
            sleepus.o spipe.o tellwait.o ttymodes.o writen.o

all:    $(LIBMISC) sleep.o

$(LIBMISC):    $(OBJS)
    $(AR) rv $(LIBMISC) $?
    $(RANLIB) $(LIBMISC)

clean:
    rm -f *.o a.out core temp.* $(LIBMISC)

include $(ROOT)/Make.libapue.inc
解析如下:
  1. 定位顶层(编译根目录root),执行shell脚本,获取平台信息,然后include包含顶层Makefile(定义编译参数)
  2. 定义打包变量LIBMISC、打包变量的依赖文件OBJS(所需依赖的.o文件),多行连续语句只用\链接。
  3. 通过依赖关系自动生成的中间文件(.o),默认执行命令:CC CFLAGS -c -o xxx.o xxx.c,所以下面的make过程(第一加粗部分)就不难理解为何是统一的格式编译libapue.a的依赖对象。
  4. all:    $(LIBMISC) sleep.o过程是先执行对象LIBMISC,然再执行sleep.o,Makefile都有按照编写顺序去执行。
  5. 打包ar过程,自动变量(LIBMISC所依赖的OBJS)的时间戳要比LIBMISC要新的时候进行打包(或更新打包)
  6. clean规则,-f强制执行rm,*.o(这里作为中间文件),core是内存映像文件(程序崩溃产生),core链接,temp*是顶层传入
  7. 最后(所有子层都有)包含的Make.libapue.inc,确保规则的目标能够正确找到libapue.a(子层详细解析),因为使用include命令,所以该行(哪怕是在文件最后一行)都会首先执行的(第二次include执行)。
  8. 下面提供编译过程,详细对照思考
h265@H265:algs4-hhc$ make -C apue.3e/lib/ (单独编译lib,方便观察)
make: Entering directory '/home/h265/sharefile/repos/trunk/algs4-hhc/apue.3e/lib' (make自动产生,无需编写)
gcc -ansi -g -I../include -Wall -DLINUX -D_GNU_SOURCE   -c -o bufargs.o bufargs.c
gcc -ansi -g -I../include -Wall -DLINUX -D_GNU_SOURCE   -c -o cliconn.o cliconn.c
····省略相同格式但不同对象的编译过程,都生成对应的.o文件,提供ar打包使用····
gcc -ansi -g -I../include -Wall -DLINUX -D_GNU_SOURCE   -c -o ttymodes.o ttymodes.c
gcc -ansi -g -I../include -Wall -DLINUX -D_GNU_SOURCE   -c -o writen.o writen.c
ar rv libapue.a bufargs.o cliconn.o clrfl.o daemonize.o error.o errorlog.o lockreg.o locktest.o openmax.o pathalloc.o popen.o prexit.o prmask.o ptyfork.o ptyopen.o readn.o recvfd.o senderr.o sendfd.o servaccept.o servlisten.o setfd.o setfl.o signal.o signalintr.o sleepus.o spipe.o tellwait.o ttymodes.o writen.o
ar: 正在创建 libapue.a
a - bufargs.o
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值