Makefile

格式

目标:依赖

       

.PHONY: clean

        命令

注释

注释: #;

 若要输入#,则使用\#

命令要以Tab键开头;


基本语法

#为注释符。

 @echo表示禁止echo回显。

= 、:= 与?=的区别

1) :=为立刻赋值,如B :=$(A)时,它只会到这句语句之前去找A的值,如A没有定义所以什么都没有输出。

2) =不是立刻赋值,而是从makefile文件最后往前找。

3) ?=含义为:如没定义,则赋值。如:TEMP ?= var 等价于
ifeq($(TEMP),undefined)
TEMP = var
endif

ifeq用法

ifeq ()

....

else 

ifeq ()

...

endif

endif

设置tab为4个空格后,输入TAB键

ctrl+v+TAB。





ifdef..else..endif

预定义宏,示例:

  HW=1                                                                                                                                               
  ifdef HW
          contxt="hello"
  else
          contxt="local"
  endif
  all:
          echo $(contxt)
  

如上例,若HW为真,则输出为hello,若HW为假,则输出为local。


ifeq...else...endif

条件编译,示例:

ifeq($(gdb),y)

         echo "debug"

else

         echo "release"

endif
make时,可以加编译选项make gdb=y使编译出debug版本;也可以在makefile文件中定义变量来实现。



$(shell pwd)中shell的意义

makefile中,要调用shell脚本。需要特殊的语法。
比如要调用xxx命令。
相应的语法是
$(shell xxx)

你直接使用xxx,比如pwd命令。人家makefile哪知道是shell命令啊。它只会把pwd当成makefile变量或者规则。
如:

p=$(shell pwd)

all:

    echo $p


ar命令

 在makefile中用ar 创建静态库.a,一般加参数rcs,即 ar rcs  libxxx.a a.o b.o;

 STRIP命令

当最终的可执行程序不需要包含调试信息时,可使用strip”去掉可执行程序中的调试符号以减小最终的程序大小。


ifeq() else endif

 条件判断 oo: $(objects)
    ifeq ($(CC),gcc)
            $(CC) -o foo $(objects) $(libs_for_gcc)
    else
            $(CC) -o foo $(objects) $(normal_libs)
    endif

awk

echo $i | awk -F ':' '{print "#define " "SERVER_"$1" " "\""$2"\""}' >> $sfile;   按照分割符:进行操作,将分割符前后的内容显示;



1、wildcard : 扩展通配符
2、notdir : 去除路径
3、patsubst :替换通配符

例子:建立一个测试目录,在测试目录下建立一个名为sub的子目录$ mkdir test$ cd test$ mkdir sub

在test下,建立a.c和b.c2个文件,在sub目录下,建立sa.c和sb.c2 个文件

建立一个简单的Makefilesrc=$(wildcard *.c ./sub/*.c)dir=$(notdir $(src))obj=$(patsubst %.c,%.o,$(dir) )

all: @echo $(src) @echo $(dir) @echo $(obj) @echo "end" 执行结果分析:第一行输出:a.c b.c ./sub/sa.c ./sub/sb.c

wildcard把 指定目录 ./ 和 ./sub/ 下的所有后缀是c的文件全部展开。

第二行输出:a.c b.c sa.c sb.cnotdir把展开的文件去除掉路径信息

第三行输出:a.o b.o sa.o sb.o

在$(patsubst %.c,%.o,$(dir) )中,patsubst把$(dir)中的变量符合后缀是.c的全部替换成.o,任何输出。或者可以使用obj=$(dir:%.c=%.o)效果也是一样的。

这里用到makefile里的替换引用规则,即用您指定的变量替换另一个变量。它的标准格式是$(var:a=b) 或 ${var:a=b}它的含义是把变量var中的每一个值结尾用b替换掉a

今天在研究makefile时在网上看到一篇文章,介绍了使用函数wildcard得到指定目录下所有的C语言源程序文件名的方法,这下好了,不用手工一个一个指定需要编译的.c文件了,方法如下:

SRC = $(wildcard *.c)

等于指定编译当前目录下所有.c文件,如果还有子目录,比如子目录为inc,则再增加一个wildcard函数,象这样:

SRC = $(wildcard *.c) $(wildcard inc/*.c)





 自动化编译;

 1) make -C dir :切换到指定目录再执行 make 过程,makefile 在这个指定目录里面;通常出现在makefile文件中;

 2) 伪目标是一个标签不是文件,所以需要指定才可以执行,如make clean;一般用.PHONY指定(指定后伪目标就可以和真正的目标重名了);一般没有依赖,但是我们可以为伪目标指定依赖并将它放在第一个使其成为默认目标,如all;

 3) STRIP的含义是当最终的可执行程序不需要包含调试信息时,可使用strip”去掉可执行程序中的调试符号以减小最终的程序大小。

 4) := 是立即变量赋值,在定义时值已经被确定;
     = 是延时变量赋值,只有在这个变量被使用时才展开,$(VAR)就是一种被使用 4) 
 5)$@ 代表目标 上例为$(BUILT_IN_OBJ)
    $^ 代表所有的依赖对象 上例第一个$^为$(OBJS),即 ifconfig.o tftp_util.oping.o,上例第二个$^为$(SRCS),即$(OBJS:.o=.c) (Makefile解释后为: ifconfig.ctftp_util.c ping.c)
    $< 代表第一个依赖对象 前面例子修改如下:
    $(BUILT_IN_OBJ) : $(OBJS)
 

        $(LD) $(LDFLAGS) -r $< -o $@
则$<表示为ifconfig.o

“%”的意思是匹配零或若干字符,例如,“%.h”表示所有以“.h”结尾的文件.
它是在GUNmake的语法层次上的,例如 vpath %.h ../headers ,该语句表示,要求make在“../headers”目录下搜索所有以“.h”结尾的文件.
*是Shell所支持的通配符,是在shell的语法层次上,*.c,一般用在shell命令里面,如:
clean:
rm -f *.o

Makefile文件

 自动化编译;

 1) make -C dir :切换到指定目录再执行 make 过程,makefile 在这个指定目录里面;通常出现在makefile文件中;

 2) 伪目标是一个标签不是文件,所以需要指定才可以执行,如make clean;一般用.PHONY指定(指定后伪目标就可以和真正的目标重名了);一般没有依赖,但是我们可以为伪目标指定依赖并将它放在第一个使其成为默认目标,如all;

 3) STRIP的含义是当最终的可执行程序不需要包含调试信息时,可使用strip”去掉可执行程序中的调试符号以减小最终的程序大小。

 4) := 是立即变量赋值,在定义时值已经被确定;
     = 是延时变量赋值,只有在这个变量被使用时才展开,$(VAR)就是一种被使用 4)
 5)$@ 代表目标 上例为$(BUILT_IN_OBJ)
    $^ 代表所有的依赖对象 上例第一个$^为$(OBJS),即 ifconfig.o tftp_util.oping.o,上例第二个$^为$(SRCS),即$(OBJS:.o=.c) (Makefile解释后为: ifconfig.ctftp_util.c ping.c)
    $< 代表第一个依赖对象 前面例子修改如下:
    $(BUILT_IN_OBJ) : $(OBJS)
 

      $(LD) $(LDFLAGS) -r $< -o $@
则$<表示为ifconfig.o


你可能感兴趣的:(Makefile)