MakeFile学习2-语法

makefile语法

什么是makefile

makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要重新编译,如何进行链接等操作。
makefile就是自动化编译,告诉make命令如何编译和链接

makefile里有什么

makefile 包含以下五个:

  1. 显示规则
  2. 隐晦规则
  3. 变量定义
  4. 文件指示
  5. 注释

makefile规则

target ... : prerequisites ...
    command
或者
target ... : prerequisites ... ;command

注意 一个是冒号,一个是分号

在同一行 可以使用分号进行分割,如果不在同一行 使用tab连接 如果命令太长可以使用反斜杠换行

参数 含义
target 目标文件。可以使Object File 也可以是执行文件,还可以是标签(Lable)
prerequisites 依赖文件,即要生成那个target所需要的文件或其他target
command make需要执行的命令

makefile 示例

当前文件存在main.c tool.c tool.c三个文件
下面吗是makefile文件内容

main :main.o tool.o
    gcc main.o tool.o -o main
.PHONY:clean
clean :
    -rm main *.o

执行 make 后输出如下

cc -c -o main.o main.c
cc -c -o tool.o tool.c
gcc main.o tool.o -o main

生成一个可执行文件main

-o :指定可执行文件名称
clean :标签,不会生成clean文件,这样大的target称为伪目标,伪目标的名字不能和文件名重复。clean一般放在文件最后
.PHONY : 显示地指明clean是一个伪目标

makefile如何工作

默认方式下,输入make命令后:

  1. make会在当前目录下找名字叫做Makefile或者makefile的文件。
  2. 如果找到,它会找文件中第一个目标文件(target)并把这个target作为最终的目标文件,如前面示例中的main
  3. 如果main文件不存在,或main所依赖的.o文件的修改时间要比main文件要新,那么他会执行后面所定义的命令来生成main文件
  4. 如果main所依赖的.o文件也存在,那么make会在当前文件中找目标为.o文件的依赖性,若找到则依据规则生成.o文件。
  5. make在用.o文件声明make的终极任务,也就是执行文件main。

Makefile中使用变量

为了makefile容易维护,在makefile中我们可以使用变量。makefile的变两个就是一个字符串,理解为C语言中定义的宏可能会更好。
比如我们声明一个变量交objects,于是我们可以很方便地在我们的makefile中通过$(objects)方式来使用这个变量了。

objects = main.o tool.o
main: $(objects)
    gcc $(objects) -o main
.PHONY:clean
clean:
    rm main $(objects)

执行make后输入如下

cc -c -o main.o main.c
cc -c -o tool.o tool.c
gcc main.o tool.o -o main

引用其他的Makefile

使用include关键字可以吧其他Makefile包含进来,include语法格式

include 

举个例子,假设有几个Makefile

a.mk b,mk c.mk还拥有一个文件叫做 # foo.make,以及一个变量$(bar)包含了e.mkf.mk

include foo.make  *.mk $(bar)
等价于
include foo.make a.mk b.mk c.mk e.mk f.mk

如果文件找不到,而你希望make时不理会哪些无法读取的文件而继续执行
可以在include前加一个减号 - 例如

-include 

环境变量

如果当前环境中定义了环境变量MAKEFILES ,那么,make会把这个变量中的值做一个类似于include的动作。这个变量中的值是其他的Makefile。用空格分隔。只是他和include不同的是,从这个环境变量中引入的Makefile的目标不会起作用,如果环境变量中定义的文件发现错误,make也会不理。但是建议不要使用这个环境变量,因为只要这个变量一被定义,那么当你使用make时,所有的Makefile都会受到他的影响。也是有时候Makefile出现奇怪的事,那么可以查看当前环境中的没有定义这个变量。

Makefile预定义变量

变量名 描述 默认值
CC C语言编译器的名称 cc
CPP C语言预处理器名称 $(CC) -E
CXX C++语言编译器的名称 g++
RM 删除文件程序的名称 rm -f
GFLAGS c语言编译器的处理选项
CPPFLAGS c语言预处理器的编译选项
CXXFLAGS C++语言编译器的编译选项

Makefile自动变量

自动变量 描述
$* 目标文件的名称,不包含拓展名
$@ 目标文件的名称,包含拓展名
$+ 所有的依赖文件,以空格隔开,可能含有重复的文件
$^ 所有的依赖文件,以空格隔开,不重复
$< 依赖项中第一个依赖文件的名称
$? 依赖项中所有比目标文件新的依赖文件

Makefile函数

不带参数


define FUNC
$(info echo "hello")
endef

$(call FUNC)

------------------------
输出 :hello

带参数


define FUNC1
$(info echo $(1) $(2))
endef

$(call FUNC1,hello,world)

------------------------
输出 :hello world

例子

有三个文件

main.c tool.c tool.h

如果不使用makefile的方式进行编译

gcc -c tool.c
gcc -c main.c
gcc -o main main.o tool.o


./main

max=8

使用makefile方式进行编译

vim makefile
main:main.o tool.o
    gcc main.o tool.o -o main
.PHONY: clean
clean:
    -rm main *.o

输出

cc    -c -o main.o main.c
cc    -c -o tool.o tool.c
gcc main.o tool.o -o main

makefile使用变量的方式进行编译

objects = main.o tool.o
main: $(objects)
    gcc $(objects) -o main
.PHONY: clean
clean:
    -rm main $(objects)

makefile使用方法

define func  // 定义方法
$(info "hello")
endef

$(call func)

define func1
$(info $(1) $(2))
endef

$(call func1,hello,world)

objects = main.o tool.o
main: $(objects)
    gcc $(objects) -o main
.PHONY: clean
clean:
    -rm main $(objects)

输出

$ make
"hello"
hello world
make: “main”已是最新。

makefile工作流程

GNU的makefile工作时的执行步骤如下

  1. 读取所有的Makefile。
  2. 读取被include的其他Makefile
  3. 初始化文件中的变量
  4. 推到隐晦规则并分析所有规则
  5. 为所有的目标文件创建依赖关系链
  6. 依据依赖关系,决定哪些目标重新生成
  7. 执行生成命令

你可能感兴趣的:(linux)