zoukankan      html  css  js  c++  java
  • Makefile研究(二)—— 完整可移植性模板

    转自:http://blog.csdn.net/jundic/article/details/17676461

    一直想写一个很全很好移植的Makefile模板,我觉得一个完整makefile 应该包含如下内容。 

    1、可以编译成 动态库.a  静态库.so  或者是直接编译成可执行文件。

    2、编译可执行文件可以指定宏 ,自有添加头文件,指定链接的各种库

    3、要能过自动生成依赖关系,能准确地捕捉到任何依赖文件的改动。

    4、如果是嵌入式系统应该还要指定链接脚本(这里暂不考虑)

    下面是我写的一个具备上面1-3点的makefile

      1 # Generic Makefile for C/C++ Program  
      2 # Author:   
      3 # Description:   
      4 # This is an easily customizable makefile template. The purpose is to  
      5 # provide an instant building environment for C/C++ programs.  
      6 #  
      7 # It searches all the C/C++ source files in the specified directories,  
      8 # makes dependencies, compiles and links to form an executable.  
      9 #  
     10 # Besides its default ability to build C/C++ programs which use only  
     11 # standard C/C++ libraries, you can customize the Makefile to build  
     12 # those using other libraries. Once done, without any changes you can  
     13 # then build programs using the same or less libraries, even if source  
     14 # files are renamed, added or removed. Therefore, it is particularly  
     15 # convenient to use it to build codes for experimental or study use.  
     16 #  
     17 # GNU make is expected to use the Makefile. Other versions of makes  
     18 #  
     19   
     20 .PHONY : all clean  
     21   
     22 # Curstomer build output file directory and filename  
     23 EXES =   
     24 DIR_EXES =   
     25 DIR_OBJS =   
     26 DIR_DEPS =  
     27 DIR_INCS =   
     28   
     29 LINK_LIBS =   
     30 LIBS_TYPE = dynamic    
     31 #LIBS_TYPE = static  
     32 DIR_LIBS =   
     33 LIBS =   
     34   
     35 # Top directory  Makefile  
     36 CURDIR = $(shell pwd)  
     37   
     38 # The C program compiler  
     39 COPTION = -O2   
     40 MACRO = -DDEBUGALL   
     41 CFLAGS += -g -werror $(MACRO) $(COPTION)  
     42 CC = gcc  
     43 AR = ar  
     44 ARFLAGES = crv  
     45   
     46 # default execute output directory  
     47 ifeq ($(DIR_EXES),)  
     48 DIR_EXES = $(TOPDIR)/build/out  
     49 endif  
     50   
     51 # defaulet libaray creat directory  
     52 ifeq ($(DIR_LIBS),)  
     53 DIR_LIBS = $(TOPDIR)/build/libs  
     54 endif  
     55   
     56 # directory  
     57 DIRS = $(DIR_OBJS) $(DIR_DEPS) $(DIR_EXES) $(DIR_LIBS)  
     58   
     59 # include directory   
     60 ifneq ($(DIR_INCS),"")  
     61 DIR_INCS := $(strip $(DIR_INCS))  
     62 DIR_INCS := $(addprefix -I,$(DIR_INCS))  
     63 endif  
     64   
     65 # build execute file   
     66 ifneq ($(EXES),)  
     67 EXES := $(addprefix $(DIR_EXES)/,$(EXES))  
     68 RMS += $(EXES)  
     69 DIR_LIBS := $(strip $(DIR_LIBS))  
     70 DIR_LIBS := $(addprefix -L,$(DIR_LIBS))  
     71 endif  
     72   
     73 # build libaray file   
     74 ifneq ($(LIBS),"")  
     75 LIBS := $(addprefix $(DIR_LIBS)/,$(LIBS))  
     76 RMS += $(LIBS)  
     77 endif  
     78   
     79 # default source code file directory  
     80 ifeq ($(DIR_SRCS),)  
     81 DIR_SRCS = .  
     82 endif   
     83   
     84 # scan source code   
     85 SRCS = $(wildcard $(DIR_SRCS)/*.c)  
     86 OBJS = $(patsubst %.c, %.o,$(notdir $(SRCS)))  
     87 OBJS := $(addprefix $(DIR_OBJS)/,$(OBJS))  
     88 RMS += $(OBJS) $(DIR_OBJS)  
     89   
     90 # dependant file   
     91 DEPS = $(patsubst %.c, %.dep,$(notdir $(SRCS)))  
     92 DEPS := $(addprefix $(DIR_DEPS)/,$(DEPS))  
     93 RMS += $(DEPS) $(DIR_DEPS)  
     94   
     95 # build execute file   
     96 ifneq ($(EXES),"")  
     97 all : $(EXES)  
     98 endif  
     99   
    100 # build library   
    101 ifneq ($(LIBS),"")  
    102 all : $(LIBS)  
    103 endif  
    104   
    105 # link libs name   
    106 ifneq ($(LINK_LIBS),"")  
    107 LINK_LIBS := $(strip $(LINK_LIBS))  
    108 LINK_LIBS := $(addprefix -l,$(LINK_LIBS))  
    109 endif  
    110   
    111 # include dependent files   
    112 ifneq ($(MAKECMDGOALS), clean)  
    113 -include $(DEPS)  
    114 endif  
    115   
    116 $(DIRS):  
    117     mkdir -p $@  
    118   
    119 # creat execute file  
    120 $(EXES) : $(DIR_OBJS) $(OBJS) $(DIR_EXES)  
    121     $(CC) $(DIR_INCS) $(CFLAGES) -o $@ $(OBJS) $(DIR_LIBS) $(LINK_LIBS)  
    122   
    123 # creat libaray file  
    124 $(LIBS) : $(DIR_LIBS) $(DIR_OBJS) $(OBJS)  
    125 # library type is static  
    126 ifeq ($(LIB_TYPE),static)  
    127     $(AR) $(ARFLAGS) $@ $(OBJS)  
    128 endif  
    129   
    130 # library type is dynamic  
    131 ifeq ($(LIB_TYPE),dynamic)  
    132     $(CC) -shared -o $@ $(OBJS)  
    133 endif  
    134   
    135 # creat object file   
    136 $(DIR_OBJS)/%.o : $(DIR_SRCS)/%.c  
    137     @echo "source files:" $<  
    138     @echo "object files:" $@  
    139 ifeq ($(LIB_TYPE),static)  
    140     $(CC) $(DIR_INCS) $(CFLAGES) -o $@ -c $<  
    141 else  
    142     $(CC) $(DIR_INCS) $(CFLAGES) -fPIC -o $@ -c $<  
    143 endif  
    144   
    145 # creat depandant file  
    146 $(DIR_DEPS)/%.dep : $(DIR_SRCS)/%.c $(DIR_DEPS)  
    147     @echo "creating depend file ..." $@  
    148     @set -e;  
    149     $(CC) $(DIR_INCS) -MM $< > $@.tmp;  
    150     sed 's,$∗.o[ :]*,$(DIR_OBJS)/1.o $@ : ,g' < $@.tmp > $@  
    151   
    152 clean:  
    153     rm -rf $(RMS)  

    对整个makefle 分析如下:

    1、line   23-33

    是当我们要将源代码编译成可执行文件还是静态库,还是动态库在这里配置就可以

    DIR_OBJS 为目标文件输出目录,DIR_DEPS为依赖文件输出目录,DIR_INC为包含头文件的目录。

    LINK_LIBS 为当生成可执行文件如果需要链接外面的库,则在这里指定库的名字。

    DIR_LIBS 为库的路径,LIBS 为库的 libXX.so 或 libXX.a 格式的名字。

    2、line   38 - 34

    为gcc 编译相关

    COPTION  为编译优化等选项

    MACRO   为编译时定义的宏配置

    3、line 44 - 109

    这些都是根据前面是生成可执行文件还是库的对应的输出配置,以及目标依赖关系

    4、line 19 - 121

    生成可执行文件的语句

    5、line 123 - 133

    生成静动态库的语句

    6、line 146 - 150

    这可以是整个makefile 的关键所在,这是生成依赖文件的地方,有人会问编译代码不就是将.c --> .o ----> 可执行文件么,表面上是这样。

    但实际上很多时候我们编译c但还包含了.h 或者是其他配置文件,当这时候.h和配置文件改变了,但当已经完整make后,但make却没检查到这种改变,导致修改后的文件无法编译进去,这时候只能make clean 才能make 。大工程中这个明显浪费很多时间。其实不能怪make不够只能,那是因将这些配置文件作为依赖关系包含进去。而makefile 只检查目标文件所依赖的文件的更新。

    在gcc 中有一个MM 很好地解决这个问题,假如 test.c 除了包含了头文件还包含了test.h test1.h 那么

    gcc -MM test.c

    结果为 test.o : test.c test.h test1.h

    sed 命令应用有点复杂但他的作用加上必要的路径,输出到test.dep文件中,这个方法在uboot 和 android ,Linux 编译系统中使用的。

    这样一个比较完整的单目录结果makefile 就写好,我们可以根据自己的需要配置成是生成可执行文件还是库,很方便移植到不是很复杂的应用当中去。

  • 相关阅读:
    Best Time to Buy and Sell Stock
    Remove Nth Node From End of List
    Unique Paths
    Swap Nodes in Pairs
    Convert Sorted Array to Binary Search Tree
    Populating Next Right Pointers in Each Node
    Maximum Subarray
    Climbing Stairs
    Unique Binary Search Trees
    Remove Duplicates from Sorted Array
  • 原文地址:https://www.cnblogs.com/computer1-2-3/p/7637421.html
Copyright © 2011-2022 走看看