学习 redis -- Makefile 篇

make 命令简介

make 命令格式:make [-f Makefile] [option] [target]

make 是一个解释 makefile 中指令的命令工具。make 工具最主要也是最基本的功能:就是通过 makefile文件 来描述源程序之间的相互关系并自动维护编译工作。而 makefile文件 需要按照某种语法进行编写,文件中需要说明如何编译各个源文件,并连接生成可执行文件,并要求定义源文件之间的依赖关系。

redis 中的 Makefile 使用

  1. $(MAKE) 代表 make 命令本身
  2. .PHONY 伪指令, 用于处理 Makefile 所在目录有与自命令重名文件的问题
  3. $@ 代表 命令传过来所有参数 makefile 中 $@ 与 bash 脚本中的含义不一样
    1. $@ 表示规则中目标
    2. $< 表示规则中的第一个依赖条件
    3. $^ 表示规则中的所有依赖条件

      1. test 1 2 3 4 5
      2. $# 是传给脚本的参数个数 ps: 5
      3. $0 是脚本本身的名字 ps: test
      4. $1是传递给该shell脚本的第一个参数 ps: 1
      5. $2是传递给该shell脚本的第二个参数 ps: 2
      6. $@ 是传给脚本的所有参数的列表 参数独立看待 ps: for 循环可循环 5 次
      7. $* 是传给脚本的所有参数的列表 所有参数整体看待 ps: “1 2 3 4 5”, for 循环循环 1 次

  4. 版本号生成

    1
    2
    3
    4
    #!/bin/sh
    GIT_SHA1=`(git show-ref --head --hash=8 2> /dev/null || echo 00000000) | head -n1`
    GIT_DIRTY=`git diff --no-ext-diff 2> /dev/null | wc -l`
    BUILD_ID=`uname -n`"-"`date +%s`
  5. 执行shell uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')

    1. := $() 赋值命令执行后的输出
    2. /dev/null 一个特殊的设备文件,这个文件接收到任何数据都会被丢弃
    3. 2>/dev/null 将标准错误的输出重定向到 /dev/null, 此处意在不输出标准错误信息, 如shell脚本失败, 只输出 not
    4. Linux 系统预留了三个文件描述符
      1. 0 标准输入 stdin
      2. 1 标准输出 stdout
      3. 2 标准错误 stderr
  6. Makefile 赋值操作
    1. = 是最基本的赋值 make会将整个makefile展开后,再决定变量的值。也就是说,变量的值将会是整个makefile中最后被指定的值
    2. := 是覆盖之前的值 变量的值决定于它在makefile中的位置,而不是整个makefile展开后的最终值
    3. ?= 是如果没有被赋值过就赋予等号后面的值
    4. += 是添加等号后面的值
  7. Makefile 中的 if 语句 及函数调用

    1
    2
    3
    4
    5
    6
    STD=-pedantic -DREDIS_STATIC=''
    ifneq (,$(findstring clang,$(CC)))
    ifneq (,$(findstring FreeBSD,$(uname_S)))
    STD+=-Wno-c11-extensions
    endif
    endif

扩展知识

  1. Makefile 规则

    targets… : prerequisites…
    [table] commands…

  2. make 工作流程
    1. make会在当前目录下找名字叫 Makefile 或 makefile 的文件
    2. 如果找到,它会找文件中的第一个目标文件(target),并把它作为最终的目标文件
    3. 递归 target 的 prerequisites, 如果不存在或者其所依赖更新, 执行对应的 command 生成自己
    4. 如果 target 文件不存在,或所依赖的文件更新,执行 command 生成 target
  3. make 命令执行步骤
    1. 读入所有的 Makefile
    2. 读入被 include 的其它 Makefile
    3. 初始化文件中的变量
    4. 推导隐晦规则,并分析所有规则
    5. 为所有的目标文件创建依赖关系链
    6. 根据依赖关系,决定哪些目标要重新生成
    7. 执行生成命令
  4. 文件搜索 VPATH vpath %.h ../headers
    1. 如果没有指明这个变量,make只会在当前的目录中去找寻依赖文件和目标文件。如果定义了这个变量,那么,make就会在当前目录找不到的情况下,到所指定的目录中去找寻文件了。
    2. vpath pattern directories, 为符合模式 pattern 的文件指定搜索目录 directories
    3. vpath pattern 清除符合模式 pattern 的文件的搜索目录
    4. vpath 清除所有已被设置好了的文件搜索目录
  5. 命令执行

    1. @ 不输出命令
    2. - 忽略错误继续执行
    3. 定义命令包

      1
      2
      3
      4
      define customCommand
      command
      command...
      endef
  6. 函数

    1. 使用方式 $(function arguments)
    2. 字符串操作函数列表 (待完善)
    3. 文件操作函数列表 (待完善)
    4. 命令函数调用方式 $(shell command args)
  7. 预定义变量, 见附表一
  8. 命令行选项, 见附表二

附表一

命令行选项 含义
-C DIR 在读取 makefile 之前改变到指定的目录 DIR
-f FILE 以指定的 FILE 文件作为 makefile
-i 忽略所有的命令执行错误
-I DIR 当包含其他 makefile 文件时,可利用该选项指定搜索目录
-n 只打印要执行的命令,但不执行这些命令
-p 显示 make 变量数据库和隐含规则
-s 在执行命令时不显示命令
-w 在处理 makefile 之前和之后,显示工作目录
-W FILE 假定文件 FILE 已经被修改

附表二

命令行选项 含义
-C DIR 在读取 makefile 之前改变到指定的目录 DIR
-f FILE 以指定的 FILE 文件作为 makefile
-i 忽略所有的命令执行错误
-I DIR 当包含其他 makefile 文件时,可利用该选项指定搜索目录
-n 只打印要执行的命令,但不执行这些命令
-p 显示 make 变量数据库和隐含规则
-s 在执行命令时不显示命令
-w 在处理 makefile 之前和之后,显示工作目录
-W FILE 假定文件 FILE 已经被修改