Makefile点滴

1. makefile中变量定义最后空格的影响

在Makefile中定义变量时,一定要注意最后一定不要有空格

举例如下,


AAA := `pwd`  # current path // 经常写注释,习惯在#前加一个或多个空格


obj: $(AAA)/a/b.txt // 此时依赖展开后为: obj:  `pwd` /a/b.txt  // 显然变成了两个依赖

     @echo xxxx


2. “order only”依赖

    举例:

    LIBS = libtest.a
    foo : foo.c | $(LIBS)
           $(CC) $(CFLAGS) $< -o $@ $(LIBS)

    “|” 左边是常规依赖(正常前提目标(Normal Prerequisites)),右边是order only依赖(命令前提目标(order-only Prerequisites))。

    当常规依赖有变化时,目标被重新编译

    但当order only依赖更新时,目标不会被重新编译,即libtest.a被更新时,foo不被给更新,但如果libtest.a有无到有时,目标重新编译

    我们需要执行某个或某些规则,但不能引起生成目标被重新生成。此时你就需要使用命令前提目标。


3. 赋值

    makefile中有两种赋值:递归赋值(或延时赋值)和直接赋值

    =  延时赋值,使用时才能确定变量的值,即使用的时候才递归展开来得到变量的值,所以也称递归赋值

   ?= 延时赋值,但只能定义第一次的延时变量,即如果之前没有定义该变量,则有=赋值相同,如果以前定义过,则不再重新定义

   := 直接赋值,即直接展开变量,不能使用后面定义变量的值,只能用前面定义好的变量的值


    define来定义变量,实质定义命令包,使用eval函数来使用,它属于递归展开式变量


   makefile执行过程:两次扫描makefile,然后执行目标。扫描是一行一行进行的,如果需要变量的值,只会查找之前变量的值,而不会查找后面。所以两次扫描后变量值的改变只会在生成目标时才是用到,也就是说递归赋值和直接赋值只对生成目标时才有效,而扫描过程中没有影响(例如使用ifeq ($(AAA),)中变量AAA的值并不会使用该语句后面的AAA的值,如果该语句之前没有对AAA赋值,则$(AAA)就时空)),举例如下:


      $(warning $(AAAA)) // 输出: 空
      ifeq ($(AAAA),"aaaa")  // 不成立
      $(error "Abort! ...")
      endif

     AAAA = aaaa 
     $(warning $(AAAA))  // 输出: aaaa
     all: $(LOCAL_PATH)/a/b/c/a.txt b.txt  //此时LOCAL_PATH为空,因为之前没有定义,在后面才有定义
         @echo "AAAA=$(AAAA)"   // 输出: aaaa

     LOCAL_PATH=`pwd`

     变量有重名时,后面的变量覆盖前面的变量。


    下面例子也说明延时赋值只是在命令行中其作用

    AAA=a

    BBB=b

    $(AAA):$(BBB)

             @echo "$(AAA)---$(BBB) //输出aaa-bbb

             @echo "$@---$<" // 输出a-b 所以 依赖是可以保存值的,而不会因为后面值的改变而改变。

    AAA=aaa

    BBB=bbb

    



4. -Wl,--no-undefined用处

    一般情况下,编译so文件时,允许没有定义的函数,只需要有函数声明即可。但在android中使用so就不能出现函数未定义了。所以android-ndk中编译出来的so总是可以被使用的,而不用担心函数未定义。原因就是编译时使用了该参数。


5. call函数

   1> error: *** commands commence before first target.  Stop.

       举例:

        define print

        @echo "Log: $1"

        endef

       

        target: abc:=$(call print,Hello)

                 $(abc)

       提示error,如标题红色部分

       如下修改可以解决,但是不知道为什么,在此注释一下,待解决

       target: abc:=$(call print,Hello)  // print函数位置必须在该调用之前,否则没定义,也就无输出

       target:

                 $(abc)

      或者直接直接调用

      target:

                 $(call print,Hello)   // print函数位置任意

      

6. gcc 编译时与位置有关(为什么啊??????)

    gcc main.c -o test  -lGLU -lglut   // 正确

    gcc  -lGLU -lglut main.c -o test  // 出现link error







你可能感兴趣的:(Makefile点滴)