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 就写好,我们可以根据自己的需要配置成是生成可执行文件还是库,很方便移植到不是很复杂的应用当中去。

  • 相关阅读:
    解上三角矩阵和下三角矩阵方程的fortran程序
    用sublimetext写fortran程序
    fortran子程序传入可变数组要在module里实现
    ubuntu wineqq 输入中文显示方格的问题
    mathtype快捷键很方便+公式上边不显示问题的解决
    滚动字符小程序-python
    传递矩阵法求简支梁固有频率的近似解 --matlab程序
    explorer.exe总是重启导致打开的文件夹关闭
    python把数据分为训练部分和测试部分的简单实现
    用python批量删掉文件名中共同存在的字符
  • 原文地址:https://www.cnblogs.com/computer1-2-3/p/7637421.html
Copyright © 2011-2022 走看看