Makefile的简单编写

1. 简介

  • 在Unix下的代码编译中,Makefile指定了一系列代码编译的规则。
  • 在编写好Makefile后,只需执行make便可轻松编译

2. 规则

Makefile以下述的规则编写:

1
2
3
4
5
6
7
8
# 目标文件:依赖文件
# (tab)编译命令

# 目标文件:main
# 依赖文件:main.o add.o mul.o sub.o div.o
# 编译命令:g++ -o main add.o mul.o sub.o div.o main.o
main:main.o add.o mul.o sub.o div.o
g++ -o main add.o mul.o sub.o div.o main.o

3. 变量、符号与函数

a. 变量的使用

  • 变量无需声明,可直接使用
  • 若其他位置需要该变量时,则必须以$(Variable)的形式引用
1
2
VIR_A = A
VIR_B = $(VIR_A) B

b. 符号

  • 赋值符号

    • = : 最容易出错 的赋值等号

      1
      2
      3
      VIR_A = A
      VIR_B = $(VIR_A) B
      VIR_A = AA

      最后VIR_B的值是AA B,而不是A B
      在make时,会把整个makefile展开,最后决定变量的值

    • ?= : 如果没有被赋值过,则赋值等号后面的操作

    • += : 追加(append)

    • := : 正常 的赋值

  • 特殊符号:

    • % : 通配符

    • %0 : 执行时的第一个参数

    • $@ : 目标文件

    • $< : 第一个依赖文件

    • $^ : 所有的依赖文件

    • $$ : 与$等价

    • 例子:

      1
      2
      3
      4
      a.out: a.c b.c
      @echo '$$@='$@ # $@=a.out
      @echo '$$<='$< # $<=a.c
      @echo '$$^='$^ # $^=a.c b.c

c. 内置函数

注:函数调用中不能在参数中添加空格,因为空格也会被视为参数的一部分

  • addprefix

    • 格式:$(addprefix prefix,<names...>)
    • 功能:为文件序列添加前缀
    1
    2
    Variable := $(addprefix src/,foo bar)
    # Variable ==> src/foo src/bar
  • addsuffix

    • 格式:$(addsuffix addsuffix,<names...>)
    • 功能:为文件序列添加后缀
    1
    2
    Variable := $(addsuffix .c,foo bar)
    # Variable ==> foo.c bar.c
  • basename

    • 格式:$(basename <names...>)
    • 功能:从文件名序列中取出各个文件名的前缀部分(除去扩展名后的剩余部分)
    1
    2
    Variable := $(basename src/foo.c src-1.0/bar.c hacks)
    # Variable ==> src/foo src-1.0/bar hacks
  • notdir

    • 格式:$(notdir <names...>)
    • 功能:文件名列表中去除所有的目录信息,只保留文件名
    1
    2
    # 去除所有的目录信息,返回的文件名列表将只有文件名
    SRC = $(notdir wildcard)
  • shell

    • 功能:执行shell命令<myCommand>并返回输出结果
    • 格式:$(shell <myCommand>)

    注:每行的shell都是一个单独的进程

    1
    CXXFLAGS := $(shell llvm-config --cxxflags)
  • subst

    • 功能:把字符串<text>中的<from>字符串替换成<to>
    • 格式:$(subst <from>,<to>,<text>)
    1
    2
    3
    4
    # 注:无需引号
    Origin := There is a big tree
    Result := $(subst a,the, $(Origin))
    # Result ==> There is the big tree
  • wildcard

    在Makefile规则中,通配符会被自动展开。但在变量的定义和函数引用时,通配符将失效。

    • 功能:函数引用时使通配符有效
    • 格式:$(wildcard <PATTERN...>)
    1
    2
    # 生成一个以空格间隔的后缀为.c的文件名列表
    Variable := $(wildcard *.c)

4. 简单的例子

命令行输入make <targetFile>即可对特定目标文件进行编译。

例:make all、make main、make clean(clean比较特殊)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#获取.cpp文件
SrcFiles=$(wildcard *.cpp)
#使用替换函数获取.o文件
ObjFiles=$(patsubst %.cpp,%.o,$(SrcFiles))
#生成的可执行文件
all:main
#目标文件依赖于.o文件
main:$(ObjFiles)
g++ -o $@ -I ../include $(SrcFiles)
#.o文件依赖于.cpp文件,通配使用,一条就够
%.o:%.cpp
g++ -c -I ../include $<

.PHONY:clean all

clean:
rm -f *.o
rm -f main

5. 参考

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2020-2021 Kiprey
  • 访问人数: | 浏览次数:

请我喝杯奶茶吧~