Makefile笔记

Makefile笔记

makefile用来制定编译的规则及其其它更复杂的操作。并且能实现整个工程的自动化编译,提高编译效率

一、基础语法

1
2
3
# Makefile 格式:
target : prerequisites
<tab> command

目标:target

  • 文件名 : 可以是多个,即使是最终目标文件

  • 操作的名字:伪目标

    • 通过 .PHONY 来声明clean是一个伪目标,而不是一个目标文件,例:
    1
    2
    3
    .PHONY: clean
    clean:
    rm *.o temp

前置条件:prerequisites

一组文件名 : 用空格分开 只要有一个前置条件的文件有过更新,目标就要重新构建

命令:command

由一行或者多行的shell命令组成,命令之前必须有tab键 1. 每行命令在一个单独的shell中执行,这些shell之间没有继承关系 2. 多行命令依赖解决: 1、加上.ONESHELL: 2、 用逗号分隔 3、添加换行转义

二、其它

注释

text
1
2
3
# 这是注释
target : prerequisites
<tab> command

回声 echoing

在执行每一条命令时都会在终端打印这条命令,在命令之前加上@可以关闭

通配符

Makefile通配符与bash一致,主要有:

    • : 可以匹配任何字符
  • ?: 匹配任意单个字符
  • […] : 匹配一个单字符范围,

模式匹配

对文件名进行类似正则运算的匹配,适应于大量同类型的文件

1
%.o : %.c

变量

变量可以用等号赋值,访问时可以使用$(Variable)来访问 所以在使用美元符号的时候可以使用$$来转义 赋值:

1
2
3
4
5
6
7
8
9
10
11
VARIABLE = value
# 在执行时扩展,允许递归扩展。

VARIABLE := value
# 在定义时扩展。

VARIABLE ?= value
# 只有在该变量为空时才设置值。

VARIABLE += value
# 将值追加到变量的尾端。

内置变量

  • $(CC) : 指向当前使用的编译器
  • $(MAKE) :指向当前使用的Make工具

自动变量

  • $@ : 指代当前需要生成的目标
  • $< : 指代第一个前置条件
  • $? : 指代比目标更新的所有前置条件
  • $^ : 指代所有前置条件

判断和循环

判断

1
2
3
4
5
ifeq ($(CC),gcc)
libs=$(libs_for_gcc)
else
libs=$(normal_libs)
endif

循环

1
2
3
4
5
LIST = one two three
all:
  for i in $(LIST); do \
      echo $$i; \
  done

函数

格式

1
2
3
$(function arguments)
# 或者
${function arguments}

shell函数

1
srcfiles := $(shell echo src/{00..99}.txt)

wildcard函数

1
srcfiles := $(wildcard src/*.txt)

subst 函数

1
$(subst from,to,text)

patsubst函数

1
$(patsubst pattern,replacement,text)

替换后缀名

1
min: $(OUTPUT:.js=.min.js)

Makefile 执行

通过make命令工具来解释makefile中的指令,makefile告诉make需要怎么去编译和链接目标程序,make还能根据当前文件情况确定哪些文件需要重新编译

1
$ make # 自动寻找Makefile
1
$ make -f Makefile
1
$ make --file=Makefile

附:编译和链接

基本流程

  1. 源文件–编译–>中间文件
  2. 中间文件–链接–>可执行文件

编译链接细节

  1. 编译时,编译器需要的是语法,函数与变量的声明是否正确,只要正确就能生成中间文件
  2. 链接时,主要是链接函数和全局变量,连接时只管中间目标文件
  3. 在中间文件过多时,可以给中间文件打包

中间文件:

  • Windows:*.obj
  • UNIX : *.o

打包文件:

  • Window : 库文件(Library File) .lib
  • Unix : Archive File, .a

参考文献

参考博客