makefile

Posted hesper

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了makefile相关的知识,希望对你有一定的参考价值。

make

make : linux自带构建器, 构建规则在makefile中

makefile文件的命名: makefile, Makefile

makefile中的规则可分为三部分: 目标, 依赖, 命令
格式:

目标:依赖
(tab缩进)命令

工作原理:
  检测依赖是否存在, 向下搜索规则, 如果有规则是用来生成查找依赖的, 执行规则中的命令
  依赖存在: 判断是否需要更新, 原则是目标的时间要晚于依赖的时间, 否则需要更新
  内部会有些构建的规则

变量定义:
  自定义变量: obj=a.o b.o c.o
  变量取值: aa=$(obj)
  makefile自带变量: 一般大写, 有些被赋值, 有些没有赋值
    CPPFLAGS: 头文件目录
    CC
  自动变量: 只能在命令中使用
    [email protected]: 规则中的目标
    $<: 规则中的第一个依赖
    $^: 规则中的所有依赖

命令参数:
  命令后加-f: 强制执行
  命令前加-: 忽略执行失败的命令, 继续向下执行其余的命令

模式匹配:
  %.o:%.c

函数: makefile中的所有的函数都有返回值
  查找指定目录下指定类型的文件: wildcard
    src = $(wildcard ./*.c)
  匹配替换: patsubst
    obj = $(patsubst %.c, %c, $(src)), 替换类型的文件, 要替换的类型的文件, 源文件

声明伪目标: 不做文件更新与是否存在的检查.PHONY

版本一

缺点: 效率地, 修改一个文件, 所有文件都会被全部重新编译

[email protected]:~/dir_test/dir_test_1/src$ cat makefile 
app:main.c add.c div.c mul.c  sub.c
    gcc main.c add.c div.c mul.c sub.c
[email protected]:~/dir_test/dir_test_1/src$ ls
add.c  div.c  head.h  main.c  makefile  mul.c  sub.c
[email protected]:~/dir_test/dir_test_1/src$ make
gcc main.c add.c div.c mul.c sub.c
[email protected]:~/dir_test/dir_test_1/src$ ls
add.c  a.out  div.c  head.h  main.c  makefile  mul.c  sub.c
[email protected]:~/dir_test/dir_test_1/src$ ./a.out 
sum = 26
[email protected]:~/dir_test/dir_test_1/src$ cat makefile 
app:main.o add.o div.o mul.o sub.o
    gcc main.o add.o div.o mul.o sub.o

main.o:main.c
    gcc main.c -c

add.o:add.c
    gcc add.c -c

div.o:div.c
    gcc div.c -c

mul.o:mul.c
    gcc mul.c -c

sub.o:sub.c
    gcc sub.c -c
[email protected]:~/dir_test/dir_test_1/src$ ls
add.c  div.c  head.h  main.c  makefile  mul.c  sub.c
[email protected]:~/dir_test/dir_test_1/src$ make
gcc main.c -c
gcc add.c -c
gcc div.c -c
gcc mul.c -c
gcc sub.c -c
gcc main.o add.o div.o mul.o sub.o
[email protected]:~/dir_test/dir_test_1/src$ ls
add.c  add.o  a.out  div.c  div.o  head.h  main.c  main.o  makefile  mul.c  mul.o  sub.c  sub.o
[email protected]:~/dir_test/dir_test_1/src$ vim add.c  # 只修改一个文件
[email protected]:~/dir_test/dir_test_1/src$ make       # 只重新编译2个文件
gcc add.c -c
gcc main.o add.o div.o mul.o sub.o

缺点: 后面的编译.o文件命令冗余

版本二

使用自定义变量和匹配替换

[email protected]:~/dir_test/dir_test_1/src$ cat makefile 
obj = main.o add.o div.o mul.o sub.o
target = app
$(target):$(obj)
    gcc $(obj) -o $(target)

%.o:%.c         # 当需要的.o文件没有时, 会进行替换
    gcc -c $< -o [email protected]
[email protected]:~/dir_test/dir_test_1/src$ ls
add.c  div.c  head.h  main.c  makefile  mul.c  sub.c
[email protected]:~/dir_test/dir_test_1/src$ make
gcc -c main.c -o main.o
gcc -c add.c -o add.o
gcc -c div.c -o div.o
gcc -c mul.c -o mul.o
gcc -c sub.c -o sub.o
gcc main.o add.o div.o mul.o sub.o -o app
[email protected]:~/dir_test/dir_test_1/src$ ls
add.c  add.o  app  div.c  div.o  head.h  main.c  main.o  makefile  mul.c  mul.o  sub.c  sub.o

使用自动变量

[email protected]:~/dir_test/dir_test_1/src$ cat makefile 
obj = main.o add.o div.o mul.o sub.o
target = app
$(target):$(obj)
    gcc $^ -o [email protected]
#   gcc $(obj) -o $(target)

%.o:%.c
    gcc -c $< -o [email protected]
[email protected]:~/dir_test/dir_test_1/src$ ls
add.c  div.c  head.h  main.c  makefile  mul.c  sub.c
[email protected]:~/dir_test/dir_test_1/src$ make
gcc -c main.c -o main.o
gcc -c add.c -o add.o
gcc -c div.c -o div.o
gcc -c mul.c -o mul.o
gcc -c sub.c -o sub.o
gcc main.o add.o div.o mul.o sub.o -o app
[email protected]:~/dir_test/dir_test_1/src$ ls
add.c  add.o  app  div.c  div.o  head.h  main.c  main.o  makefile  mul.c  mul.o  sub.c  sub.o
[email protected]:~/dir_test/dir_test_1/src$ cat makefile 
obj = main.o add.o div.o mul.o sub.o
target = app
$(target):$(obj)
    gcc $^ -o [email protected]
#   gcc $(obj) -o $(target)
[email protected]:~/dir_test/dir_test_1/src$ make
cc    -c -o main.o main.c
cc    -c -o add.o add.c
cc    -c -o div.o div.c
cc    -c -o mul.o mul.c
cc    -c -o sub.o sub.c
gcc main.o add.o div.o mul.o sub.o -o app
[email protected]:~/dir_test/dir_test_1/src$ ls
add.c  add.o  app  div.c  div.o  head.h  main.c  main.o  makefile  mul.c  mul.o  sub.c  sub.o

版本三

使用makefile函数查找与替换

[email protected]:~/dir_test/dir_test_1/src$ cat makefile 
src = $(wildcard ./*.c)
obj = $(patsubst %.c, %.o, $(src))
target = app
$(target):$(obj)
    gcc $^ -o [email protected]
#   gcc $(obj) -o $(target)

%.o:%.c
    gcc -c $< -o [email protected]
[email protected]:~/dir_test/dir_test_1/src$ ls
add.c  div.c  head.h  main.c  makefile  mul.c  sub.c
[email protected]:~/dir_test/dir_test_1/src$ make
gcc -c mul.c -o mul.o
gcc -c main.c -o main.o
gcc -c add.c -o add.o
gcc -c div.c -o div.o
gcc -c sub.c -o sub.o
gcc mul.o main.o add.o div.o sub.o -o app
[email protected]:~/dir_test/dir_test_1/src$ ls
add.c  add.o  app  div.c  div.o  head.h  main.c  main.o  makefile  mul.c  mul.o  sub.c  sub.o

版本四

添加清除功能, 编写一个清理项目的规则

[email protected]:~/dir_test/dir_test_1/src$ cat makefile 
src = $(wildcard ./*.c)
obj = $(patsubst %.c, %.o, $(src))
target = app
$(target):$(obj)
    gcc $^ -o [email protected]

%.o:%.c
    gcc -c $< -o [email protected]

hello:
    echo "haha"
[email protected]:~/dir_test/dir_test_1/src$ ls
add.c  div.c  head.h  main.c  makefile  mul.c  sub.c
[email protected]:~/dir_test/dir_test_1/src$ make
gcc -c mul.c -o mul.o
gcc -c main.c -o main.o
gcc -c add.c -o add.o
gcc -c div.c -o div.o
gcc -c sub.c -o sub.o
gcc mul.o main.o add.o div.o sub.o -o app
[email protected]:~/dir_test/dir_test_1/src$ ls
add.c  add.o  app  div.c  div.o  head.h  main.c  main.o  makefile  mul.c  mul.o  sub.c  sub.o
[email protected]:~/dir_test/dir_test_1/src$ cat makefile 
src = $(wildcard ./*.c)
obj = $(patsubst %.c, %.o, $(src))
target = app
$(target):$(obj)
    gcc $^ -o [email protected]

%.o:%.c
    gcc -c $< -o [email protected]

clean:
    rm $(obj) $(target)
[email protected]:~/dir_test/dir_test_1/src$ ls
add.c  div.c  head.h  main.c  makefile  mul.c  sub.c
[email protected]:~/dir_test/dir_test_1/src$ make
gcc -c mul.c -o mul.o
gcc -c main.c -o main.o
gcc -c add.c -o add.o
gcc -c div.c -o div.o
gcc -c sub.c -o sub.o
gcc mul.o main.o add.o div.o sub.o -o app
[email protected]:~/dir_test/dir_test_1/src$ ls
add.c  add.o  app  div.c  div.o  head.h  main.c  main.o  makefile  mul.c  mul.o  sub.c  sub.o
[email protected]:~/dir_test/dir_test_1/src$ make clean
rm  ./mul.o  ./add.o  ./main.o  ./div.o  ./sub.o app
[email protected]:~/dir_test/dir_test_1/src$ ls
add.c  div.c  head.h  main.c  makefile  mul.c  sub.c
[email protected]:~/dir_test/dir_test_1/src$ cat makefile 
src = $(wildcard ./*.c)
obj = $(patsubst %.c, %.o, $(src))
target = app
$(target):$(obj)
    gcc $^ -o [email protected]

%.o:%.c
    gcc -c $< -o [email protected]

clean:
    -mkdir /haha    # 忽略执行失败的命令, 继续向下执行
    rm $(obj) $(target)
[email protected]:~/dir_test/dir_test_1/src$ ls
add.c  div.c  head.h  main.c  makefile  mul.c  sub.c
[email protected]:~/dir_test/dir_test_1/src$ make
gcc -c mul.c -o mul.o
gcc -c main.c -o main.o
gcc -c add.c -o add.o
gcc -c div.c -o div.o
gcc -c sub.c -o sub.o
gcc mul.o main.o add.o div.o sub.o -o app
[email protected]:~/dir_test/dir_test_1/src$ make clean
mkdir /haha # 忽略执行失败的命令, 继续向下执行
mkdir: cannot create directory ‘/haha’: Permission denied
makefile:11: recipe for target 'clean' failed
make: [clean] Error 1 (ignored)
rm  ./mul.o  ./add.o  ./main.o  ./div.o  ./sub.o app
[email protected]:~/dir_test/dir_test_1/src$ ls
add.c  div.c  head.h  main.c  makefile  mul.c  sub.c
[email protected]:~/dir_test/dir_test_1/src$ touch clean
[email protected]:~/dir_test/dir_test_1/src$ make clean
make: 'clean' is up to date.

版本五

声明伪目标: 不被做文件更新, 是否存在的检查

[email protected]:~/dir_test/dir_test_1/src$ cat makefile 
src = $(wildcard ./*.c)
obj = $(patsubst %.c, %.o, $(src))
target = app
$(target):$(obj)
    gcc $^ -o [email protected]

%.o:%.c
    gcc -c $< -o [email protected]

.PHONY:clean
clean:
    -mkdir /haha    # 忽略执行失败的命令, 继续向下执行
    rm $(obj) $(target)
[email protected]:~/dir_test/dir_test_1/src$ ls
add.c  clean  div.c  head.h  main.c  makefile  mul.c  sub.c
[email protected]:~/dir_test/dir_test_1/src$ make
gcc -c mul.c -o mul.o
gcc -c main.c -o main.o
gcc -c add.c -o add.o
gcc -c div.c -o div.o
gcc -c sub.c -o sub.o
gcc mul.o main.o add.o div.o sub.o -o app
[email protected]:~/dir_test/dir_test_1/src$ ls
add.c  add.o  app  clean  div.c  div.o  head.h  main.c  main.o  makefile  mul.c  mul.o  sub.c  sub.o
[email protected]:~/dir_test/dir_test_1/src$ make clean
mkdir /haha # 忽略执行失败的命令, 继续向下执行
mkdir: cannot create directory ‘/haha’: Permission denied
makefile:12: recipe for target 'clean' failed
make: [clean] Error 1 (ignored)
rm  ./mul.o  ./add.o  ./main.o  ./div.o  ./sub.o app
[email protected]:~/dir_test/dir_test_1/src$ ls
add.c  clean  div.c  head.h  main.c  makefile  mul.c  sub.c

进阶版

[email protected]:~/dir_test/dir_test_1$ cat makefile 
target=app
CPPFLAGES=./include
path=./src
src=$(wildcard ./src/*.c)
obj=$(patsubst %.c, %.o, $(src))

$(target):$(obj)
    gcc $^ -o [email protected]

%.o:%.c
    gcc -c $< -I $(CPPFLAGES) -o [email protected]
[email protected]:~/dir_test/dir_test_1$ tree
.
├── include
│?? └── head.h
├── lib
├── makefile
└── src
    ├── add.c
    ├── div.c
    ├── main.c
    ├── mul.c
    └── sub.c

3 directories, 7 files
[email protected]:~/dir_test/dir_test_1$ make
gcc -c src/mul.c -I ./include -o src/mul.o
gcc -c src/main.c -I ./include -o src/main.o
gcc -c src/add.c -I ./include -o src/add.o
gcc -c src/div.c -I ./include -o src/div.o
gcc -c src/sub.c -I ./include -o src/sub.o
gcc src/mul.o src/main.o src/add.o src/div.o src/sub.o -o app
[email protected]:~/dir_test/dir_test_1$ ls
app  include  lib  makefile  src

以上是关于makefile的主要内容,如果未能解决你的问题,请参考以下文章

Makefile文件语法

使用带有 NMake 样式 Makefile 的 clang-cl 无法回显

如何使用 makefile 使用 Visual Studio 编译代码

重建后的Makefile重新编译代码需要很多时间

Makefile

Makefile步步为营