• Makefile 易忘规则记录


    Makefile 易忘规则记录

    主要用于记录一些Makefile中容易忘记的规则等

    粗略规则

    target... : prerequisites ...
    [tab] command
    ...
    

    易忘规则

    伪目标声明

    .PHONY: clean
    clean:
    [tab] rm ./*.o
    

    自动推导

    a.o 的缺省依赖 a.c

    注释

    Makefile 中只有行注释

    p := /home/wangha    #注释
    

    当注释以上面方式时,要注意,p实际上为'/home/wangha ',后面是携带着空格的

    命令

    命令的执行必须以[TAB]开头,除非命令是紧跟在依赖规则的';'后面的

    引用其他Makefile

    include <filename1> <filename2> #允许使用通配符
    -include <*.h> # 忽略无法读取的文件
    

    指定目录搜寻头文件或依赖文件

    VPATH = src:../others # src和../others
    

    vpath的三种用法

    1. vpath <pattern> <directories>

      为符合pattern的文件在directories上也进行搜索

    2. vpath <pattern>

      清除符合pattern的文件的搜索目录

    3. vpath

      清除所有已被设置好的文件搜索目录

    多目标中的$> $@

    $> 表示多目标中对应的依赖

    $@ 表示多目标中对应的目标

    替换

    source = foo.c bar.c
    include $(source:.c=.d) # 转化为foo.d bar.d
    include $(source:%.c=%.d) # 静态模式的转换
    

    命令执行

    exec:
    [TAB] :cd /home/abc; pwd # 只有在一行时才会有效
    exec2: 
    [TAB] : cd/home
    [TAB] : pwd # 依旧是Makefile的目录下
    

    忽略ERROR

    方式一:

    -command 加上'-'后,不管出错与否,继续执行

    方式二:

    全局忽略,make的参数中加'-i'或者'--ignore-errors'

    嵌套执行的变量传递

    export <var1 ...>;
    

    仅仅局限于传递到下层的Makefile

    如果传递所有变量 则只需要export即可

    等于号

    = 普通的定义变量,但存在着递归定义的问题

    := 修复了递归定义问题,但前面的变量不能使用后面的变量,如

    a := $(b) a.o #a的实际值是a.o
    b := b.o
    

    ?= 例如b?=bar,如果b已经定义过了,则什么也不做

    变量嵌套

    x = $(y)
    y = z
    z = Hello
    a := $($(x))
    

    此处a应该为Hello,自行推导

    override的使用

    在make的时候,会指定一些参数,在Makefile中对这些变量赋值是会被忽略的,如果希望修改,则需要使用override,语法i如下

    override <var1>; =<value>;
    override <var1>; +=<more>;
    override define foo
    bar
    endef
    

    define的使用

    define double-echo
    echo abc
    echo $(abc)
    endef
    

    局部变量

    a  := bar.c
    tmp : a:=foo.c
    tmp : $(a)
    [TAB] gcc -o b.o $(a) #在tmp的范围内,a为foo.c
    

    模式变量

    %.o : CFLAGS = -O
    

    使用时

    a.o: a.c
    [TAB] : $(CC) $(CFLAGS) a.o a.c
    

    上述例子为,给所有的 .o 文件,在编译时候,自动添加-O

    条件关键词

    1. ifeq

      ifeq (<arg1>, <arg2>)
      ifeq '<arg1>' '<arg2>'
      ifeq "<arg1>" "<arg2>"
      ifeq "<arg1>" '<arg2>'
      ifeq '<arg1>' "<arg2>"
      
    2. ifneq

      用法同上

    3. ifdef

      foo =
      ifdef foo
          frobozz = yes
      else
          frobozz = no
      endif
      

      上述例子,由于foo没有赋值,故 frobozz为no

    4. ifndef

      用法同上

    函数的调用

    $(func-name argus)
    

    例子:将空格全部转换为','

    comma:= ,
    empty:=
    space:= $(empty) $(empty)
    foo:= a b c
    bar:= $(subst $(space),$(comma),$(foo))
    

    foreach函数

    $(foreach <var>,<list>,<text>)
    

    功能:对list中的每一个赋值给var,并执行text

    例子:

    names := a b c d
    files := $(foreach n,$(names), $(n).o)
    

    files 的值为a.o b.o c.o d.o

    if函数

    $(if <condition>,<then-part>)
    $(if <condition>,<then-part>,<else-part>)
    

    返回值,如果 <condition> 为真(非空字符串),那个 <then-part> 会是整个函数的返回值,如果 <condition> 为假(空字符串),那么 <else-part> 会是整个函数的返回值。如果 <else-part> 没有被定义,那么,整个函数返回空字串。

    call函数

    $(call <expression>,<parm1>,<parm2>,...,<parmn>)
    

    返回值: <expression> 的返回值就是 call 函数的返回值

    例子 foo=a b

    reverse =  $(1) $(2)
    foo = $(call reverse,a,b)
    

    origin函数

    $(origin <variable>)
    

    功能:告诉你这个变量是哪里来

    返回值:

    undefined: 如果 <variable> 从来没有定义过

    default: 如果 <variable> 是一个默认的定义,比如“CC”这个变量

    environment: 如果 <variable> 是一个环境变量,并且当Makefile被执行时, -e 参数没有被打开。

    file: 如果 <variable> 这个变量被定义在Makefile中。

    command line: 如果 <variable> 这个变量是被命令行定义的。

    override: 如果 <variable> 是被override指示符重新定义的。

    automatic: 如果 <variable> 是一个命令运行中的自动化变量。

    常用于 :判断当前的这个变量到底来自于哪里

    例子:

    ifdef bletch
        ifeq "$(origin bletch)" "environment"
            bletch = barf, gag, etc.
        endif
    endif
    

    shell函数

    调用/bin/sh来执行一些功能

    contents := $(shell cat foo)
    

    控制make的函数

    $(error <text ...>)
    $(warning <text ...>)
    

    可用于检测Makefile运行时的信息,决定你继续执行OR报Error或者Warning和停止

    例子,当发现有ERROR_001时,报错

    ifdef ERROR_001
        $(error error is $(ERROR_001))
    endif
    

    make的退出码

    0-succeed

    1-error

    2-如果你使用了make的“-q”选项,并且make使得一些目标不需要更新

    指定Makefile

    make -f 123.mk

    指定目标

    推荐采取以下方式

    .PHONY: all
    all: prog1 prog2 prog3 prog4
    

    makefile中的目标生成参照规则

    • all:这个伪目标是所有目标的目标,其功能一般是编译所有的目标。
    • clean:这个伪目标功能是删除所有被make创建的文件。
    • install:这个伪目标功能是安装已编译好的程序,其实就是把目标执行文件拷贝到指定的目标中去。
    • print:这个伪目标的功能是例出改变过的源文件。
    • tar:这个伪目标功能是把源程序打包备份。也就是一个tar文件。
    • dist:这个伪目标功能是创建一个压缩文件,一般是把tar文件压成Z文件。或是gz文件。
    • TAGS:这个伪目标功能是更新所有的目标,以备完整地重编译使用。
    • check和test:这两个伪目标一般用来测试makefile的流程。

    检查规则

    -n: 不执行参数,这些参数只是打印命令,不管目标是否更新,把规则和连带规则下的命令打印出来,但不执行,这些参数对于我们调试makefile很有用处。

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

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

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

  • 相关阅读:
    神器Tampermonkey的安装使用
    记一些不错的知识博客
    redis入门到精通系列(九):redis哨兵模式详解
    redis入门到精通系列(八):redis的高可用--主从复制详解
    redis入门到精通系列(七):redis高级数据类型详解(BitMaps,HyperLogLog,GEO)
    redis入门到精通系列(六):redis的事务详解
    redis入门到精通系列(五):redis的持久化操作(RDB、AOF)
    redis入门到精通系列(四):Jedis--使用java操作redis详解
    jsp乱码
    Tomcat 9遇到错误开着怎么关闭
  • 原文地址:https://www.cnblogs.com/wangha/p/13300812.html
Copyright © 2020-2023  润新知