本文共 5490 字,大约阅读时间需要 18 分钟。
Makefile学习路径: 或者陈皓的《跟我一起写Makefile》,可以说是gnu 官方make文件的译文。
unpv1工程文件下载地址:
解压缩提取归档文件,执行configure脚本后如下图:
主要分析4部分:./ Makefile ./Make.defines ./tcpcliserv/Makefile ./lib/Makefile
./Makefile.defines :
## This file is generated by autoconf from "Make.defines.in".## This is the "Make.defines" file that almost every "Makefile" in the# source directories below this directory include.# The "../" in the pathnames actually refer to this directory, since# "make" is executed in all the subdirectories of this directory.## System = i686-pc-linux-gnuCC = gccCFLAGS = -I../lib -g -O2 -D_REENTRANT -WallLIBS = ../libunp.a -lpthreadLIBS_XTI = ../libunpxti.a ../libunp.a -lpthreadRANLIB = ranlib# Following is the main library, built from all the object files# in the lib/ and libfree/ directories.LIBUNP_NAME = ../libunp.a# Following is the XTI library, built from all the object files# in the libxti/ directory.LIBUNPXTI_NAME = ../libunpxti.a# Following are all the object files to create in the lib/ directory.LIB_OBJS = connect_nonb.o connect_timeo.o daemon_inetd.o daemon_init.o dg_cli.o dg_echo.o error.o get_ifi_info.o gf_time.o host_serv.o family_to_level.o mcast_leave.o mcast_join.o mcast_get_if.o mcast_get_loop.o mcast_get_ttl.o mcast_set_if.o mcast_set_loop.o mcast_set_ttl.o my_addrs.o read_fd.o readline.o readn.o readable_timeo.o rtt.o signal.o signal_intr.o sock_bind_wild.o sock_cmp_addr.o sock_cmp_port.o sock_ntop.o sock_ntop_host.o sock_get_port.o sock_set_addr.o sock_set_port.o sock_set_wild.o sockfd_to_family.o str_cli.o str_echo.o tcp_connect.o tcp_listen.o tv_sub.o udp_client.o udp_connect.o udp_server.o wraplib.o wrapsock.o wrapstdio.o wrappthread.o wrapunix.o write_fd.o writen.o writable_timeo.o# Following are all the object files to create in the libfree/ directory.LIBFREE_OBJS = in_cksum.o inet_ntop.o inet_pton.o# Following are all the object files to create in the libgai/ directory.LIBGAI_OBJS = # Following are all the object files to create in the libroute/ directory.LIBROUTE_OBJS = get_rtaddrs.o if_indextoname.o if_nameindex.o if_nametoindex.o net_rt_iflist.o net_rt_dump.o sock_masktop.o# Following are all the object files to create in the libxti/ directory.LIBXTI_OBJS = wrapxti.o xti_accept.o xti_flags_str.o xti_getopt.o xti_ntop.o xti_ntop_host.o xti_rdwr.o xti_setopt.o xti_str_opts.o xti_tlook_str.oCLEANFILES = core core.* *.core *.o temp.* *.out typescript* \ *.lc *.lh *.bsdi *.sparc *.uw该Makefile文件目的是为了定义一些变量方便下层Makefile文件使用,变量总是字符串的,会在读取Makefile文件时展开,但不会全部都展开,采用延迟机制,即在 若该变量所在的规则属于最终目标的依赖关系规则链中,该依赖决定被使用时,才在内部展开。
./Makefile
include ./Make.definesall: @echo "Nothing to make in this directory" @echo "Please read the README file"clean: rm -f $(CLEANFILES) distclean: rm -f $(CLEANFILES) config.cache config.log config.status config.h Make.defines Makefile
引用上层的Make.defines文件,使用3个伪目标,all .clean .distclean all作为第一目标,也是最终目标 所以make 总会执行echo命令,因为@,所以不会打印该命令。
通过make clean 或 make distclean 达到不同程度的清除 。
./lib/Makefileinclude ../Make.definesall: ${LIB_OBJS} ar rv ${LIBUNP_NAME} $? ${RANLIB} ${LIBUNP_NAME}clean: rm -f ${PROGS} ${CLEANFILES}
变量LIB_OBJS是lib下函数源文件生成的中间目标文件集,ar命令将其打包成$(LIBUNP_NAME),即../libunp.a 自动化变量 $?指代依赖目标中所有比库libunp.a新的链接文件, 然后 ranlib libunp。
当给静态库增建一个成员时(加入一个.o文件到静态库中),“ar”可直接 将需要增加的.o文件简单的追加到静态库的末尾。之后当我们使用这个库进行连接生成可执行文件时,链接程序“ld”却提示错误,这可能是:主程序使用了之 前加入到库中的.o文件中定义的一个函数或者全局变量,但连接程序无法找到这个函数或者变量。
这个问题的原因是:之前我们将编译完成 的.o文件直接加入到了库的末尾,却并没有更新库的有效符号表。链接程序进行链接时,在静态库的符号索引表中无法定 位刚才加入的.o文件中定义的函数或者变量。这就需要在完成库成员追加以后让加入的所有.o文件中定义的函数(变量)有效,完成这个工作需要使用另外一个 工具“ranlib”来对静态库的符号索引表进行更新。 我们所使用到的静态库(文档文件)中,存在这样一个特殊的成员,它的名字是 “__.SYMDEF”。它包含了静态库中所有成员所定义的有效符号(函数名、 变量名)。因此,当为库增加了一个成员时,相应的就需要更新成员“__.SYMDEF”,否则所增加的成员中定义的所有的符号将无法被连接程序定位。完成 更新的命令是: ranlib ARCHIVEFILE./tcpcliserv/Makefile
include ../Make.definesPROGS = tcpcli01 tcpcli04 tcpcli05 tcpcli06 \ tcpcli07 tcpcli08 tcpcli09 tcpcli10 \ tcpserv01 tcpserv02 tcpserv03 tcpserv04 \ tcpserv08 tcpserv09 tcpservselect01 tcpservpoll01 tsigpipeall: ${PROGS}tcpcli01: tcpcli01.o ${CC} ${CFLAGS} -o $@ tcpcli01.o ${LIBS}tcpcli04: tcpcli04.o ${CC} ${CFLAGS} -o $@ tcpcli04.o ${LIBS}tcpcli05: tcpcli05.o ${CC} ${CFLAGS} -o $@ tcpcli05.o ${LIBS}tcpcli06: tcpcli06.o ${CC} ${CFLAGS} -o $@ tcpcli06.o ${LIBS}tcpcli07: tcpcli07.o ${CC} ${CFLAGS} -o $@ tcpcli07.o ${LIBS}tcpcli08: tcpcli08.o str_cli08.o ${CC} ${CFLAGS} -o $@ tcpcli08.o str_cli08.o ${LIBS}tcpcli09: tcpcli09.o str_cli09.o ${CC} ${CFLAGS} -o $@ tcpcli09.o str_cli09.o ${LIBS}tcpcli10: tcpcli10.o ${CC} ${CFLAGS} -o $@ tcpcli10.o ${LIBS}tcpcli11: tcpcli11.o str_cli11.o ${CC} ${CFLAGS} -o $@ tcpcli11.o str_cli11.o ${LIBS}tcpserv01: tcpserv01.o ${CC} ${CFLAGS} -o $@ tcpserv01.o ${LIBS}tcpserv02: tcpserv02.o sigchldwait.o ${CC} ${CFLAGS} -o $@ tcpserv02.o sigchldwait.o ${LIBS}tcpserv03: tcpserv03.o sigchldwait.o ${CC} ${CFLAGS} -o $@ tcpserv03.o sigchldwait.o ${LIBS}tcpserv04: tcpserv04.o sigchldwaitpid.o ${CC} ${CFLAGS} -o $@ tcpserv04.o sigchldwaitpid.o ${LIBS}tcpserv08: tcpserv08.o str_echo08.o sigchldwaitpid.o ${CC} ${CFLAGS} -o $@ tcpserv08.o str_echo08.o sigchldwaitpid.o \ ${LIBS}tcpserv09: tcpserv09.o str_echo09.o sigchldwaitpid.o ${CC} ${CFLAGS} -o $@ tcpserv09.o str_echo09.o sigchldwaitpid.o \ ${LIBS}tcpservselect01: tcpservselect01.o ${CC} ${CFLAGS} -o $@ tcpservselect01.o ${LIBS}tcpservpoll01: tcpservpoll01.o ${CC} ${CFLAGS} -o $@ tcpservpoll01.o ${LIBS}tsigpipe: tsigpipe.o ${CC} ${CFLAGS} -o $@ tsigpipe.o ${LIBS}clean: rm -f ${PROGS} ${CLEANFILES}使用all 来 完成链接成多个最终目标$(PROGS),而且指定每一个目标的规则。