• Makefile教程


    1 Makefile语法和规则

    语法:

    targets : prerequisites
    	command
    	...
    

    targets : prerequisites ; command
    	command
    

    其中:

    • target为生成目标, 一般使用文件名或伪目标作为target, 多个target用空格分开,可使用通配符。 除了指定要生成的target, 其他target若没有被依赖则不会执行。要生成的target通过make target命令指定, 不指定则第一个target为默认target。

    • prerequisite可以是target、文件, 若prerequisite有同名的target, 会先按规则执行同名target下的command。

    • command 如果在新行必须以Tab开头; 若一行有多条语句, 用分号;分隔。(以Tab开头的都会被当做command, 所以Makefile其他语句前不能使用Tab, 排版应使用空格)

      command结果只对当前行有效(每行command处于不同进程下)。例子:

      exec:
      	cd /home/raina
      	pwd  # 没有切换路径, 仍是当前目录
      
      exec:
      	cd /home/raina; pwd  # 成功切换到/home/raina 
      

    规则:

    • 仅当target不存在或prerequisite中有一个文件比target新时才会执行下面的command。
    • 没有prerequisite的target仅当target不存在时command才执行(注意自动推导可能会为target添加依赖)。

    2 make运行

    Makefile使用make命令运行, 将Makefile文件名保存成Makefilemakefile, 然后在终端运行make命令, 会寻找当前目录下的Makefilemakefile文件, 自动运行。

    2.1 make的选项

    make -n  
    	# 仅显示命令, 不执行命令
    make -s
    	# 禁止所有命令语句本身的显示
    make -f xxx
    	# 指定makefile文件为xxx
    make -t
    	# 更新目标文件时间
    make -q
    	# 寻找目标是否存在, 存在不会输出, 不存在打印错误信息
    make -B
    	# 所有目标都需要重新编译
    make -c dir
    	# 指定读取Makefile的目录
    make -e
    	# 环境变量将覆盖Makefile内定义的变量
    make -I dir
    	# 添加头文件查找路径
    make -r
    	# 禁止make任何隐含规则
    make -R
    	# 禁止make使用任何作用于变量上的规则
    

    2.2 make执行过程

    Makfile文件内容:

    test : main.o
    	gcc -o test main.o
    main.o : main.c
    	gcc -c -o main.o main.c
    
    1. make会在当前目录下寻找“Makefile”或“makefile”文件
    2. 找到后会找到Makefile中第一个target,也就是上面例子中的test
    3. test的依赖main.o有对应的生成规则, 转去main.o:main.c
    4. 如果main.o不存在, 或当前目录下的main.c比main.o新, 就会执行下面的gcc -c -o main.o main.c; 若main.o比main.c新, 下面给的command就不会执行
    5. 若执行了main.o下的命令, 说明main.o已经更新了, test下的命令就会执行; 若main.o没有重新生成, 则比较当前目录下的main.o和test, 若main.o更新则执行gcc -o test main.o, 否则不执行。

    在make的过程中,如果没有依赖的生成规则, 路径下也没有该依赖文件,或者command执行出错,make会直接退出。

    3 Makefile特殊字符

    • 单行注释: #

    • 换行符:

    • 转义字符: (若要转义’(‘符号, 需要用`)$`表示)

    • 通配符: Makefile支持shell的*?[...]通配符;

    • 模式匹配符: %

    • 不显示命令: @, 执行的command语句默认会被显示到中断, 若不希望make执行过程中显示某command, 则在前面添加@符号:

      all: 
      	@echo hhhhhh
      

    4 变量

    4.1 变量的定义和使用

    定义:

    var = value
    

    变量在声明时必须赋初值, Makefile没有数据类型, 变量的定义类似与C/C++的宏, 但是可以改变其值。

    例子:

    # 若当前目录下有a.o、b.o、c.o三个文件
    objs = *.o
    # objs的值就是*.o, 而不是通配符展开后的结果
    

    Makefile变量定义的位置没有要求, 可以使用后面定义的变量。

    变量的命名规则:

    • 变量名可以使用字符、数字、下划线, 可以以数字开头
    • 变量名不能包含: # = 空字符
    • 变量名大小写敏感

    **使用: **

    $var
    $(var)
    ${var}
    

    若使用没有定义的变量, 其值将为空。

    4.2 多行值的变量

    若变量的值有多行, 使用define ... endef来定义:

    define var  # var为变量名
    val-part1  # var的值
    val-part2
    ...
    endef
    

    4.3 命令行变量

    在命令行定义变量:

    make var=value
    

    注意:

    • 等号两边不能加空格;

    • 若Makefile文件中有和命令行变量同名的变量, 在Makefile中改变该变量值的语句会被忽略(包括define的多行值的变量和目标变量);

    • 在Makefile若要修改命令行变量的值, 需在前面添加override 提示符:

      override var=value
      

    4.4 自动化变量

    自动化变量 说明
    $@ 表示target
    $< 表示第一个prerequisite
    $^ 所有的prerequisite的集合, 空格分隔, 重复的prerequisite会合并
    $+ 所有的prerequisite, 空格分隔, 重复的prerequisite不合并
    $? 所有比target新的prerequisite的集合, 以空格分隔

    4.5 模式变量

    模式变量: 包含%的变量。

    使用:

    类似与shell的*通配符:

    %.o : CFLAG = -o  # 定义一个目标变量, 作用于以’.o‘结尾的target
    

    Makefile静态模式规则:

    %.o: %.c  # %.c中%的值为target与%.o匹配到的%的值
        gcc -c  $< -o $@
    
    OBJS = a.o b.o
    
    all: $(OBJS) c.o
    
    # 仅对OBJS内的元素有效, c.o不会匹配此规则
    $(OBJS): %.o: %.c  # a.o的依赖为a.c, b.o的依赖为b.c
    	gcc -c  $< -o $@
    

    4.6 目标变量

    目标变量仅在作用的target范围内有效, 类似于局部变量。

    定义目标变量只需在变量定义前加其作用的target和冒号:

    main : CFLAGS = -o  # 仅在main目标范围内有效
    main.o : CFLAGS = -c -o  # 仅在main.o目标范围内有效
    
    main : main.o
    	gcc $(CFLAGS) main main.o  # gcc -o main main.o
    	
    main.o : main.c
    	gcc $(CFLAGS) main.o main.c  # gcc -c -o main main.o
    

    4.7 内置变量

    $(CURDIR): 当前所在路径

    $(MAKE_VERSION): make的版本号

    5 赋值运算符

    = 基本的赋值, 若变量后面被重新赋值, 会被覆盖

    x = 1
    y = $(x)
    all:
    	echo $(y)  # 2
    x = 2
    

    := 若右值含变量, 则使用当前位置该变量的值(而不是整个Makefile展开后的值)

    x = 1
    y := $(x)
    all:
    	echo $(y)  # 1
    x = 2
    

    += 追加变量的值(会用空格分隔)

    var = a
    var += b
    all:
    	echo $(var)  # a b
    

    6 伪目标

    .PHONY用于标记伪目标, 被标记为伪目标的target, 即使当前路径下target已经存在且为最新, 也会执行下面的command。即伪目标一经调用, 一定执行。

    例子:

    .PHONY: clean cleanobj  # 标记clean和cleanobj为伪目标
    clean: cleanobj
    	rm -f main
    cleanobj:
    	rm -f *.o
    

    常见伪目标:

    • all : 编译所有目标
    • clean: 删除所有被make创建的文件
    • install: 安装已编译好的程序, 将目标执行文件拷贝到指定路径
    • print: 列出改变过的源文件
    • dist: 创建一个压缩文件, 一般是将tar压缩成gz文件
    • TAGS: 更新所有目标, 以完整地重新编译使用
    • check或test: 测试makefile流程
    • tar: 将源程序打包备份

    7 条件判断

    判断已定义:

    ifdef var-name  # var-name为变量名, 不加$
      ... # 不能用Tab锁紧, 只能使用空格
    else  # else分支可以没有
      ...
    endif
    

    判断未定义:

    ifndef var-name
      ... 
    else
      ...
    endif
    

    判断相等:

    ifeq (arg1, arg2)
    # 或 ifeq 'arg1' 'arg2'
    # 或 ifeq "arg1" "arg2"
      ... 
    else
      ...
    endif
    

    判断不相等:

    ifneq (arg1, arg2)
    # 或 ifneq 'arg1' 'arg2'
    # 或 ifneq "arg1" "arg2"
      ... 
    else
      ...
    endif
    

    注意: make 是在读取 Makefile 时就计算条件表达式的值, 并根据条件表达式的值来选择语句, 所以, 最好不要把自动化变量(如“$@”等)放入条件表达式中, 因为自动化变量是在运行时才有的。

    8 函数的使用

    使用方法:

    $(func args)
    

    ${func args}
    

    常用函数:

    $(subset from, to, text)
    # 功能: 把字串text中的from字符串替换成to
    # 返回值: 被替换后的字符串
    
    $(patsubst pattern, replacement, text)
    # 功能: 把text中符合pattern的元素替换成replacement
    # 返回值: 被替换后的字符串
    
    $(dir paths)
    # 功能: 取出每个path的所在目录(最后一个/及之前的内容, 没有/为当前目录)
    #       多个path用空格分开
    # 返回值: 返回所在目录, 当前目录返回./
    
    $(notdir paths)
    # 功能: 取出每个path的文件命名
    # 返回值: 取到的文件名
    

    此文原创禁止转载,转载文章请联系博主并注明来源和出处,谢谢!
    作者: Raina_RLN https://www.cnblogs.com/raina/

  • 相关阅读:
    切换svn用户
    表session查询
    http请求响应头信息
    map遍历的四种方法
    java i/o读写
    excel导出
    平安医保权限管理关系
    json发送hppt请求
    weblogic配置路径
    《神经网络和深度学习》系列文章十五:反向传播算法
  • 原文地址:https://www.cnblogs.com/raina/p/12342043.html
Copyright © 2020-2023  润新知