高性能协程库State Thread Library源代码剖析之一Makefile详解

来源:互联网 发布:ubuntu tar 编辑:程序博客网 时间:2024/05/17 08:23

任何一个优秀的软件项目,都有一套合理高效的管理工具,无论c,c++还是java,要了解一个项目的全貌,比如由哪些模块组成,弄清项目是如何管理,组织的,便顺其自然。而且弄清楚模块之间的关系后,看代码更有针对性,分块肢解,各个击破,最终融会贯通。

我很讨厌上来就从代码的入口就讲解代码,因为你是怎么知道入口的,没讲。任何一行代码都是有存在价值的,包括工程项目里的任何一个文件,不管是源代码文件还是测试脚本,无论文档还是Makefile,一个优秀的工程师不会放过任何一个细节,就像把一个复杂的傅里叶变换转换成3 + 2 = 5这么浅显的道理。

管理c项目,大家脱口而出,用Makefile。可是根据我的经验,有几位仔细研究过呢,一般都是拷贝别人的改改。可是这样永远停留在模仿的阶段,而且是低级模仿,缺少创新。很多搞技术的人都自诩有追求,这不正是应该追求的地方。

搞java的人都知道make命令,搞c的更有理由知道,我们把一个项目解开,一般都是configure,make,make install。下面就分析下State Thread Library的Makefile,下面的分析是基于我的虚拟机进行的。


默认的make会让用户指定OS和BUILD变量,make linux-debug
$(MAKE) OS="LINUX" BUILD="DBG"

EXTRA_OBJS  = $(TARGETDIR)/md.o = $(OS)_$(shell uname -r)_$(BUILD)/md.o = LINUX_3.19.0-25-generic_DBG/md.o
SFLAGS      = -fPIC
LDFLAGS     = -shared -soname=$(SONAME) -lc = -shared -soname=libst.$(DSO_SUFFIX).$(MAJOR) -lc
            = -shared -soname=libst.so.1 -lc
OTHER_FLAGS = -Wall
DEFINES     += -DMD_HAVE_EPOLL

CFLAGS      += $(DEFINES) $(OTHER_FLAGS) $(EXTRA_CFLAGS)
            = (-DLinux -DMD_HAVE_EPOLL -DDEBUG) (-Wall -g) ()

ST_ALL      = $(TARGETDIR) $(LIBRARIES) $(HEADER) $(EXAMPLES) $(DESC)
            = LINUX_3.19.0-25-generic_DBG $(SLIBRARY) $(DLIBRARY) $(TARGETDIR)/st.h examples st.pc
            = LINUX_3.19.0-25-generic_DBG $(TARGETDIR)/st.h $(TARGETDIR)/libst.$(DSO_SUFFIX).$(VERSION) $(TARGETDIR)/st.h examples st.pc
            = LINUX_3.19.0-25-generic_DBG
                创建目录
              LINUX_3.19.0-25-generic_DBG/libst.a     
              LINUX_3.19.0-25-generic_DBG/libst.so.1.9
              LINUX_3.19.0-25-generic_DBG/st.h
              examples
                st.pc 根据st.pc.in,替换@VERSION@变量,生成st.pc

$(SLIBRARY): $(OBJS)
    $(AR) $(ARFLAGS) $@ $(OBJS)
    ar -rv LINUX_3.19.0-25-generic_DBG/libst.a $(OBJS)
    $(RANLIB) $@
    ranlib LINUX_3.19.0-25-generic_DBG/libst.a
    rm -f obj; $(LN) $(LNFLAGS) $(TARGETDIR) obj
    ln -s LINUX_3.19.0-25-generic_DBG obj

OBJS        = $(TARGETDIR)/sched.o \
              $(TARGETDIR)/stk.o   \
              $(TARGETDIR)/sync.o  \
              $(TARGETDIR)/key.o   \
              $(TARGETDIR)/io.o    \
              $(TARGETDIR)/event.o
OBJS        += $(EXTRA_OBJS)    

$(TARGETDIR)/md.o: md.S
    $(CC) $(CFLAGS) -c $< -o $@
$(TARGETDIR)/%.o: %.c common.h md.h
    $(CC) $(CFLAGS) -c $< -o $@

cc  -DLINUX -DMD_HAVE_EPOLL -DDEBUG -Wall -g  -c sched.c -o LINUX_3.19.0-25-generic_DBG/sched.o    
...
cc  -DLINUX -DMD_HAVE_EPOLL -DDEBUG -Wall -g  -c md.S -o LINUX_3.19.0-25-generic_DBG/md.o
    
$(DLIBRARY): $(OBJS:%.o=%-pic.o)
    $(LD) $(LDFLAGS) $^ -o $@
    动态库内的库名叫做libst.so.1,如果程序连接了新升级的库,只需要将这个新库拷贝到目录下面后,对其以soname做一个符号链接就能调用。
    ld -shared -soname=libst.so.1 -lc xxx-pic.o ...  LINUX_3.19.0-25-generic_DBG/libst.so.1.9
    if test "$(LINKNAME)"; then                             \ libst.so
            cd $(TARGETDIR);                                \ LINUX_3.19.0-25-generic_DBG
            rm -f $(SONAME) $(LINKNAME);                    \ libst.so.1 libst.so
            $(LN) $(LNFLAGS) $(FULLNAME) $(SONAME);         \ ln -s libst.so.1.9 libst.so.1
            $(LN) $(LNFLAGS) $(FULLNAME) $(LINKNAME);       \ ln -s libst.so.1.9 libst.so
    fi

优先匹配此规则    
$(TARGETDIR)/%-pic.o: %.c common.h md.
    $(CC) $(CFLAGS) $(SFLAGS) -c $< -o $@

$(<F)表示依赖文件的文件名,不包含路径    
%-pic.o: %.o
    rm -f $@; $(LN) $(LNFLAGS) $(<F) $@
    
cc  -DLINUX -DMD_HAVE_EPOLL -DDEBUG -Wall -g  -fPIC -c sched.c -o LINUX_3.19.0-25-generic_DBG/sched-pic.o
...汇编的.o和静态库的一样,直接创建符号链接
rm -f LINUX_3.19.0-25-generic_DBG/md-pic.o; ln -s md.o LINUX_3.19.0-25-generic_DBG/md-pic.o
    
$(HEADER): public.h
    rm -f $@
    cp public.h $@    


examples::
    @echo Making $@
    @cd $@; $(MAKE) CC="$(CC)" CFLAGS="$(CFLAGS)" OS="$(OS)" TARGETDIR="$(TARGETDIR)"
    进入examples目录,make CC=cc CFLAGS="..." OS="LINUX" TARGETDIR="LINUX_3.19.0-25-generic_DBG"
    编译lookupdns,proxy,server三个程序
    
cc -DLINUX -DMD_HAVE_EPOLL -DDEBUG -Wall -g  -I../LINUX_3.19.0-25-generic_DBG -c res.c -o ../LINUX_3.19.0-25-generic_DBG/res.o
cc -DLINUX -DMD_HAVE_EPOLL -DDEBUG -Wall -g  -I../LINUX_3.19.0-25-generic_DBG lookupdns.c
    ../LINUX_3.19.0-25-generic_DBG/res.o ../LINUX_3.19.0-25-generic_DBG/libst.a -lresolv  
    -o ../LINUX_3.19.0-25-generic_DBG/lookupdns    
    
cc -DLINUX -DMD_HAVE_EPOLL -DDEBUG -Wall -g  -I../LINUX_3.19.0-25-generic_DBG proxy.c ../LINUX_3.19.0-25-generic_DBG/libst.a  
    -o ../LINUX_3.19.0-25-generic_DBG/proxy
    
cc -DLINUX -DMD_HAVE_EPOLL -DDEBUG -Wall -g  -I../LINUX_3.19.0-25-generic_DBG -c error.c -o ../LINUX_3.19.0-25-generic_DBG/error.o
cc -DLINUX -DMD_HAVE_EPOLL -DDEBUG -Wall -g  -I../LINUX_3.19.0-25-generic_DBG server.c ../LINUX_3.19.0-25-generic_DBG/error.o
    ../LINUX_3.19.0-25-generic_DBG/libst.a  -o ../LINUX_3.19.0-25-generic_DBG/server


0 0