Makfile编写的基本范例

来源:互联网 发布:好老师淘宝店视频教学 编辑:程序博客网 时间:2024/04/30 10:11

 

一.变量
例子:
CC = gcc
引用变量前需要添加$: 如$(CC)
 
Makefile 变量定义
(1).Makefile变量定义跟Shell变量定义刚好相反! 
 Shell  变量定义时, =  两边不能有空格. 
 Makefile 变量定义, =  两边一定要有空格 
(2) Makefile变量定义要独立于规则之外, 
 在Makefile当中,所有Shell环境变量都是缺省当做Makefile变量,并且在Makefile中,可以用export把自己变量变成环境变量 
    export语句可以独立在规则之外 
 境变量也是多个Makefile之 通讯方法之一 
(3)  =  与:=  区别 
 两者都用于变量赋值,:=是简单赋值,=带递归引用 
 如= 后面是变量, 则变量本身值可能还要进行运算 
 :=  只是简单赋值, 后面变量只简单取值, 没有定义变量取为空, 一般比较安全 
 假设CFLAGS 预先定义有值, 则CFLAGS = $(CFLAGS)-g 变成无限递归调用, 最后变成最终堆栈溢出,正确写法是CFLAGS :=
$(CFLAGS) -g
  #这里foo最终值为Huh,因为foo后面bar还要做递归调用,而ugh也会做递归调用 
                   foo = $(bar) 
                   bar = $(ugh) 
                   ugh = Huh? 
 #这里foo最终值为空,定义foo时,bar并未定义,这里取空. 
     foo := $(bar) 
                   bar := $(ugh) 
                   ugh := Huh?
GNU make 的主要预定义变量(1) 
   (l) GNU make有许多预定义变量,这些变量具有特殊的含义,可在规则中使用。 
   (2) 除这些变量外,GNU make 还将所有的环境变量作为自己的预定义变量。 
                  预定义变量                      含义 
                    $<            第一个依赖文件的名称。
                    $@            目标的完整名称。
                    $^            所有的依赖文件,以空格分开,不包含重复的依赖文件。 
                    $*            不包含扩展的目标文件名称。 
                    $+            所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件。              
                    $?            所有的依赖文件,以空格分开,这些依赖文件的修改日期比目标的创建日期晚。    
                    $%            如果目标是归档成员,则该变量表示目标 归档成员名称。例如,
      如果目标 称为mytarget.so(image.o),则$@为 mytarget.so,而$% 为image.o。
GNU make   的主要预定义变量(2) 
                    AR            归档维护程序名称,默认值为ar 
                    ARFLAGS       归档维护程序的选项 
                    AS            汇编程序名称,默认值为as  
                    ASFLAGS       汇编程序的选项。 
                    CC            C  编译器名称,默认值为cc 
                    CCFLAGS       C  编译器的选项。 
                    CPP           C  预编译器名称,默认值为$(CC) -E       
                    CPPFLAGS      C  预编译的选项。 
                    CXX           C++  编译器名称,默认值为g++          
                    CXXFLAGS      C++  编译器的选项。
        FC            FORTRAN  编译器名称,默认值为f77       
                    FFLAGS        FORTRAN  编译器的选项。
 
变量的替换(待补充)
VPATH变量
vpath 关键字
 

二.隐含规则
GNU make 支持两种类型的隐含规则:1.后缀规则  2.模式规则
1.后缀规则(Suffix Rule):
 后缀规则定义了将一个具有某个 后缀的文件(例如,.c 文件)转换为具有另外一种后缀的文件(例如,.o 文件)的方法。每
个后缀规 则以两个成对出现的后缀名定义,例如,将 .c 文件转换为 .o 文件的后缀规则可定义为: 
.c.o: 
    $(CC) $(CCFLAGS) $(CPPFLAGS) -c -o $@ $<
2.模式规则(pattern rules)
 这种规则更加通用,因为可以利用模式规则定义更加复杂的依赖性规则。 模式规则看起来非常类似于正则规则,但在目标名称
的前面多了一个 % 号,同时可用来定义目标和依赖 文件之间的关系,例如下面的模式规则定义了如何将任意一个 X.c 文件转换为 X.o
文件: 
%.o:%.c 
    $(CC) $(CCFLAGS) $(CPPFLAGS) -c -o $@ $<
缺省规则,所有规则执行前调用 
%::
   touch $@
或 
.DEFAULT :
   touch $@

常见的隐含规则
 编译C程序
执行命令为“$(CC) -c $(CPPFLAGS) $(CFLAGS)”。
编译C++程序
执行命令为“$(CXX) -c $(CPPFLAGS) $(CFLAGS)”。建议使用“.cc”作为C++源文件的后缀,而不是“.C”
汇编和需要预处理的汇编程序
“$(AS) $(ASFLAGS)”
链接单一的object文件
“$(CC) $(LDFLAGS) N.o $(LOADLIBES) $(LDLIBS)”
但一般建议每个Makefile都用自己隐含规则来代替缺省规则,这样比较容易读懂,并且容易调整
 
 
例子
以动态库作为参考
例子1
all:main
main:hello_main.o libhello.so
    gcc hello_main.o -L.  -lhello  -o main
hello_main.o:hello_main.c
    gcc  -c hello_main.c   -o hello_main.o  -I.
libhello.so:hello.o
    gcc   -shared   hello.o    -o  libhello.so
hello.o:hello.c
    gcc  -c -fpic  hello.c  -o hello.o
clean:
    -rm -f  *.o    main  libhello.so
 
run:main
    export LD_LIBRARY_PATH=.;./main
 
例子2:
CC = gcc
EXECUTE = main
LIBHELLO = libhello.so
OBJS = hello_main.o
CCFLAGS = -fpic
LDFLAGS = -L.  -lhello
LIBOBJS = hello.o
 
all:$(EXECUTE)
 
$(EXECUTE):$(LIBHELLO) $(OBJS)
    $(CC) $^ $(LDFLAGS)  -o $@
 
$(LIBHELLO):$(LIBOBJS)
    $(CC)  -shared $^   -o $@ 
 
%.o:%.c
    $(CC) -c $<  -o  $@  $(CCFLAGS)
 
clean:
    rm -f  *.o  $(OBJS) $(LIBHELLO) $(EXECUTE)
 
run:$(EXECUTE)
   export LD_LIBRARY_PATH=.;./$(EXECUTE)
  
输入:make
备注:在编写makefile的文件时一般的情况下的-o应该是小写,不是大写,下面给出两种不同写法的样本实例
1.(此makfile文件的c文件有3个read_lock.c-write_lock.c-lock_set.c其中read_lock.c和write_lock.c在其头文件中包含lock_set.c具体的可以参见嵌入式Linux应用程序开发第二版-华清远见的文件io编程)
EXEC_WR = write_lock
OBJS_WR = write_lock.o
EXEC_RD = read_lock
OBJS_RD = read_lock.o
HEADERS = 
CC = gcc
INC = -I.
CFLAGS = ${INC} -g 
all:${EXEC_WR} ${EXEC_RD}
${EXEC_WR} : ${OBJS_WR}
${CC} ${CFLAGS} ${LDFLAGS} -o $@ ${OBJS_WR}
${EXEC_RD} : ${OBJS_RD}
${CC} ${CFLAGS} ${LDFLAGS} -o $@ ${OBJS_RD} 
${OBJS_WR} : ${HEADERS}
${OBJS_RD} : ${HEADERS}
.PHONY : clean
clean :
-rm -f ${OBJS_WR} ${EXEC_WR} ${OBJS_RD} ${EXEC_RD}
2.参加小车大赛时候自己写的比较简洁的makefile文件
car_control: camera.c extraio.c wf_trans.c car_control.c
arm-linux-gcc camera.c extraio.c wf_trans.c car_control.c -Wall -O2 -o car_control_3 -lpthread
clean:
rm car_control_3