self-confidence,the source of all the power

导航

Makefile系列之二 : 命令

一、显示命令 echo
  “@”字符可以控制命令是否在屏幕上显示,如
    @echo 正在编译XXX模块...... 

  输出:

    正在编译XXX模块......

  如果没有“@"则输出 :

    echo 正在编译XXX模块......

    正在编译XXX模块......

二、make参数

  下面列举了所有GNU make 3.80版的参数定义。
  1)make  “-n”或“--just-print”

    ——只显示命令,但不会执行命令。

  make  “-s”或“--slient”  

    ——全面禁止命令的显示。

  2)make  “-i”或“--ignore-errors”

    ——Makefile中所有命令都会忽略错误。而如果某规则是以“.IGNORE”作为目标的,那么该规则中的所有命令将会忽略错误。

  注意 : makefile是由许多规则组成,而规则又由目标、依赖及命令组成,每当命令运行完后,make会检测每个命令的返回码,如果命令返回成功,那么make会执行下一条命令,当规则中所有的命令成功返回后,这个规则就算是成功完成了。如果一个规则中的某个命令出错了(命令退出码非零),那么make就会终止执行当前规则,这将有可能终止所有规则的执行。而有些命令执行不成功并不会影响后续命令的执行,所以为了让命令继续执行,可以通过在命令前加“-”来忽略执行命令的错误,如

      clean:
        -rm -f *.o   #忽略删除文件时遇到的错误,让命令继续执行

  3)make “-w”或“--print-directory”

    ——会在make的过程中输出目前的工作目录的信息。比如,如果下级make目录是“/home/hchen/gnu/make”,当使用“make -w”来执行时,那么当进入该目录时,屏幕会输出

      make: Entering directory `/home/hchen/gnu/make'.
  而在完成下层make后离开目录时,屏幕会输出:
      make: Leaving directory `/home/hchen/gnu/make'
  当你使用“-C”参数来指定make下层Makefile时,“-w”会被自动打开的。如果参数中有“-s”(“--slient”)或是“--no-print-directory”,那么,“-w”总是失效的。

  4)“-b” “-m”
    ——这两个参数的作用是忽略和其它版本make的兼容性。
  5)“-B” “--always-make”
    ——认为所有的目标都需要更新(重编译)。
  6) “-C <dir>” “--directory=<dir>”
    ——指定读取makefile的目录。如果有多个“-C”参数,make的解释是后面的路径以前面的作为相对路径,并以最后的目录作为被指定目录。如:

      “make –C ~hchen/test –C prog” 等价于 “make –C ~hchen/test/prog”。

  7) “--debug[=<options>]”
    ——输出make的调试信息。它有几种不同的级别可供选择,如果没有参数,那就是输出最简单的调试信息。下面是<options>的取值:
      a —— 也就是all,输出所有的调试信息。(会非常的多)
      b —— 也就是basic,只输出简单的调试信息。即输出不需要重编译的目标。
      v —— 也就是verbose,在b选项的级别之上。输出的信息包括哪个makefile被解析,不需要被重编译的依赖文件(或是依赖目标)等。
      i —— 也就是implicit,输出所以的隐含规则。
      j —— 也就是jobs,输出执行规则中命令的详细信息,如命令的PID、返回码等。
      m —— 也就是makefile,输出make读取makefile,更新makefile,执行makefile的信息。
    “-d” 相当于 “--debug=a”。
  8)“-e” “--environment-overrides”
    ——指明环境变量的值覆盖makefile中定义的变量的值。
  9)“-f=<file>” “--file=<file>” “--makefile=<file>”
    ——指定需要执行的makefile。
  10) “-h” “--help”
    ——显示帮助信息。
  11)“-i” “--ignore-errors”
    ——在执行时忽略所有的错误。
  12)“-I <dir>” “--include-dir=<dir>”
    ——指定一个被包含makefile的搜索目标。可以使用多个“-I”参数来指定多个目录。
  13) “-j [<jobsnum>]” “--jobs[=<jobsnum>]”
    ——指同时运行命令的个数。如果没有这个参数,make运行命令时能运行多少就运行多少。如果有一个以上的“-j”参数,那么仅最后一个“-j”才是有效的。(注意这个参数在MS-DOS中是无用的)
  14) “-k” “--keep-going”
    ——出错也不停止运行。如果生成一个目标失败了,那么依赖于其上的目标就不会被执行了。
  15)“-l <load>” “--load-average[=<load]” “—max-load[=<load>]”
    ——指定make运行命令的负载。
  16)“-n” “--just-print” “--dry-run” “--recon”
    ——仅输出执行过程中的命令序列,但并不执行。
  17)“-o <file>” “--old-file=<file>” “--assume-old=<file>”
    ——不重新生成的指定的<file>,即使这个目标的依赖文件新于它。
  18)“-p” “--print-data-base”
    ——输出makefile中的所有数据,包括所有的规则和变量。这个参数会让一个简单的makefile都会输出一堆信息。如果你只是想输出信息而不想执行makefile,你可以使用“make -qp”命令。如果你想查看执行makefile前的预设变量和规则,你可以使用“make –p –f /dev/null”。这个参数输出的信息会包含着你的makefile文件的文件名和行号,所以,用这个参数来调试你的makefile会是很有用的, 特别是当你的环境变量很复杂的时候。
  19)“-q” “--question”
    ——不运行命令,也不输出。仅仅是检查所指定的目标是否需要更新。如果是0则说明要更新,如果是2则说明有错误发生。
  20)“-r” “--no-builtin-rules”
    ——禁止make使用任何隐含规则。
  21)“-R” “--no-builtin-variabes”
    ——禁止make使用任何作用于变量上的隐含规则。
  22)“-s” “--silent” “--quiet”
    ——在命令运行时不输出命令的输出。
  23)“-S” “--no-keep-going” “--stop”
    ——取消“-k”选项的作用。因为有些时候,make的选项是从环境变量“MAKEFLAGS”中继承下来的。所以你可以在命令行中使用这个参数来让环境变量中的“-k”选项失效。
  24)“-t” “--touch”
    ——相当于UNIX的touch命令,只是把目标的修改日期变成最新的,也就是阻止生成目标的命令运行。
  25)“-v” “--version”
    ——输出make程序的版本、版权等关于make的信息。
  26)“-w” “--print-directory”
    ——输出运行makefile之前和之后的信息。这个参数对于跟踪嵌套式调用make时很有用。
  27)“--no-print-directory”
    ——禁止“-w”选项。
  28) “-W <file>” “--what-if=<file>” “--new-file=<file>” “--assume-file=<file>”
    ——假定目标<file>需要更新,如果和“-n”选项使用,那么这个参数会输出该目标更新时的运行动作。如果没有“-n”那么就像运行UNIX的“touch”命令一样,使得<file>的修改时间为当前时间。
  29)“--warn-undefined-variables”
    ——只要make发现有未定义的变量,那么就输出警告信息。

三、执行命令

  如果要让上一条命令的结果应用在下一条命令时,必须用分号分隔这两条命令。比如你的第一条命令是cd命令,如:
示例一:
  exec:
    cd /home/hchen
    pwd
示例二:
  exec:
    cd /home/hchen; pwd
  当执行“make exec”时,第一个例子中的cd没有作用,pwd会打印出当前的Makefile目录,而第二个例子中,cd就起作用了,pwd会打印出“/home/hchen”。

四、命令包定义

  如果Makefile中出现一些相同命令序列,那么我们可以为这些相同的命令序列定义一个变量。定义这种命令序列的语法以“define”开始,以“endef”结束,如:
      define run-yacc
        yacc $(firstword $^)
        mv y.tab.c $@
      endef
   “run-yacc”是这个命令包的名字,不能与Makefile中的变量重名。在
“define”和“endef”中的两行就是命令序列。这个命令包中的第一个命令是运行Yacc程序,因为Yacc程序总是生成“y.tab.c”的文件,所以第二行的命令就是把这个文件改改名字。
五、嵌套执行make

  在一些大的工程中,我们会把我们不同模块或是不同功能的源文件放在不同的目录中,我们可以在每个目录中都书写一个该目录的Makefile,这有利于让我们的Makefile变得更加地简洁,而不至于把所有的东西全部写在一个Makefile中,这样会很难维护我们的Makefile,这个技术对于我们模块编译和分段编译有着非常大的好处。
  例如,我们有一个子目录叫subdir,这个目录下有个Makefile文件,来指明了这个目录下文件的编译规则。那么我们总控的Makefile可以这样书写:
      subsystem:
        cd subdir && $(MAKE)
  
其等价于:
      subsystem:
        $(MAKE) -C subdir
  
定义$(MAKE)宏变量可以让我们更方便地为make添加一些参数,这样比较利于维护。这两个例子的意思都是先进入“subdir”目录,然后执行make命令。
  
我们把这个Makefile叫做“总控Makefile”,总控Makefile的变量可以传递到下级的Makefile中(如果你显式的声明),但是不会覆盖下层的Makefile中所定义的变量,除非指定了“-e”参数。
  如果你要传递变量到下级Makefile中,那么你可以使用这样的声明:
      export <variable ...>
  
如果你不想让某些变量传递到下级Makefile中,那么你可以这样声明:
      unexport <variable ...>
  

      export variable = value
  其等价于:
      variable = value
      export variable
  其等价于:
      export variable := value
  传递所有的变量,那么,只要一个export就行了。后面什么也不用跟,表示传递所有的变量。
六、检查规则

  1)不想makefile中的规则执行起来,只是检查一下命令或是执行的序列。
          
“-n”
          “--just-print”
          “--dry-run”
          “--recon”
    不执行参数,这些参数只是打印命令,不管目标是否更新,把规则和连带规则下的命令打印出来,但不执行,这些参数对于我们调试makefile很有用处。
  
2)

          “-t”
          “--touch”
    这个参数的意思就是把目标文件的时间更新,但不更改目标文件。也就是说,make假装编译目标,但不是真正的编译目标,只是把目标变成已编译过的状态。
  
3)

          “-q”
          “--question”
    这个参数的行为是找目标的意思,如果目标存在,那么其什么也不会输出,当然也不会执行编译,如果目标不存在,其会打印出一条出错信息。
  
4)

          “-W <file>”
          “--what-if=<file>”
          “--assume-new=<file>”
          “--new-file=<file>”
  这个参数需要指定一个文件。一般是是源文件(或依赖文件),Make会根据规则推导来运行依赖于这个文件的命令,一般来说,可以和“-n”参数一同使用,来查看这个依赖文件所发生的规则命令。

posted on 2013-12-22 00:31  漩涡鸣人  阅读(880)  评论(0编辑  收藏  举报