目录
make工程管理
一、概述
实际项目开发中,源码文件数量都不会只有少数几个。如果一个由上百个文件的代码构成的项目在编译过一遍之后,若只对一个或少数几个文件进行了修改,再从头到尾将每一个文件都重新编译是个比较繁琐的过程。为此,引入了make工程管理器的概念,工程管理器指管理较多的文件,它是自动管理器能根据文件时间自动发现更新过的文件而减少编译的工作量(类比软件的编译功能),同时make也是一个命令(可执行程序),当使用make命令时,默认的操作对象是同路径下的名为Makefile的文件,同时通过读入Makefile文件来执行大量的编译工作。
附: make工程管理详细资料
二、使用步骤
1、准备好需要编译的工程
2、编写Makefile文件
基本语法规则:
target: dependency_files //目标项:依赖项 目标名随便定义
TAB键 command //必须以tab键开头,command编译命令
注意:在写command命令行的时候,必须要在前面按TAB键
如果依赖项或命令过长,可以加 \ ,换行再写
解释:
目标项:一般填写需要生成文件,比如工程最终可执行文件、库文件、目标文件等。也可以填写其他任意的名称(伪目标)
依赖项:一般填写生成目标项所依赖的文件
command:一般填写如何通过依赖项生成目标项(可以是多条语句)
当使用make 目标 命令时,则会根据make原则,可能会执行相应的command的内容
3、完成编译
①第一次会整体编译,make找寻默认的Makefile的规则是在当前目录下依次找三个文件“GNUmakefile”、“makefile”和“Makefile”。其按顺序找这三个文件,一旦找到,就开始读取这个文件并执行。命令过程中产生*.o文件。
②再make,如果文件没有改变,就不会编译。
①如果只改变a.c,执行make就会把与a.c有关的文件再编译,而不会编译其他未改变的文件,从而减少编译工作量。
Makefile中一般有一个clean,用于清除编译产生文件。
三、make常用参数
1、-f 指定文件
make -f my_makefile
如果不想使用Makefile作为文件名,可以通过-f指定文件名
2、-C 指定Makefile文件路径
make -C . .
去上一级目录寻找Makefile文件
3、-B 强制全部重新编译
make -B
make 命令不会编译那些自从上次编译之后就没有更改的文件,但是,如果你想覆盖 make 这种默认的行为,你可以使用 -B 选项。
4、-d Debug模式
make -d
Debug模式,输出有关文件和检测时间的详细信息。
三、伪目标
.PHONY是Makefile文件的关键字,表示它后面列表中的目标均为伪目标。
.PHONY:b
b:
echo 'hello'
#通常用@echo "hello" 若加上了@则执行该命令不显示命令本身
上面的clean就是一个伪目标,伪目标通常用在清理文件、强制重新编译、压缩解压等情况下。
四、变量
随着软件项目的变大、变复杂,源文件也越来越多,如果采用前面的方式写Makefile文件,将会使Makefile也变得复杂而难于维护。通过make支持的变量,可以写出通用性较强的Makefile文件。
Makefile中变量分类:用户自定义变量,预定义变量,自动变量,环境变量。
1、自定义变量
变量:用来代替一个文本字符串,通常代替经常使用或较长的文本
变量名是不包括“ :”、“ #”、“ =”、前置空白和尾空白的任何字符串
注:#表示行注释
定义方法 | 说明 |
---|---|
变量名:=变量值 | A := main.c,用A代替main.c |
变量名+=变量值 | B := 123 B += 4 ,此时B的值是123 4 |
变量名=变量值 | A=3 ,不常用,容易产生递归错误 |
引用变量:使用 $(变量名) 或 ${变量名} 引用变量的值
使用变量的Makefile文件:
Objects = main.o test.o
EXE = main
$(EXE):$(Objects)
gcc main.o test.o -o main
main.o:main.c
gcc -c main.c -o main.o
test.o:test.c
gcc -c test.c -o test.o
.PHONY:clean rebuild
clean:
rm -f *.o
2、变量替换
对于一个已经定义的变量,可以使用“替换引用”将其值中的后缀字符(串)使用指定的字符(字符串)替换。格式为“ $(VAR:A=B)”(或者“ ${VAR:A=B}”),意思是,将变量“ VAR”中所有“ A”字符结尾的字替换为“ B”结尾的字。“结尾”的含义是空格之前(变量值多个字之间使用空格分开)。而对于变量其它部分的“ A”字符不进行替换。例如:
A := a.o b.o c.o
B := $(A:.o=.c)
由于$(A:.o=.c)意思是引用A变量值,并将该数值中的所有以.o结尾的字全部替换为以.c结尾
B变量的值为 a.c b.c c.c
一般使用B := $(A:%.o=%.c) 替换B := $(A:.o=.c)
(这里%可以理解为通配符(在引用变量值中))
3、自动变量
自动变量:指在使用的时候,自动用特定的值替换。
变量 | 说明 |
---|---|
$@ | 当前规则的目标文件 |
$< | 当前规则的第一个依赖文件 |
$^ | 当前规则的所有依赖文件,以逗号分隔 |
$? | 规则中日期新于目标文件的所有相关文件列表,逗号分隔 |
$(@D) | 目标文件的目录名部分 |
$(@F) | 目标文件的文件名部分 |
使用自动变量改进Makefile
Sources = main.c test.c
Objects = $(Sources:.c=.o)
EXE = main
$(EXE):$(Objects)
gcc $^ -o $@
main.o:main.c
gcc -c $^ -o $@
test.o:test.c
gcc -c $^ -o $@
.PHONY:clean rebuild
clean:
rm -f *.o
4、预定义变量
预定义变量:内部事先定义好的变量,这些变量一般是有固定的初值,并且有些的值是为空的。
AR:库文件打包程序默认为ar
AS:汇编程序,默认为as
CC:c编译器默认为cc
CPP:c预编译器,默认为$(CC) -E
CXX:c++编译器,默认为g++
RM:删除,默认为rm -f
ARFLAGS:库选项,无默认
ASFLAGS:汇编选项,无默认
CFLAGS:c编译器选项,无默认
CPPFLAGS:c预编译器选项,无默认
CXXFLAGS:c++编译器选项
使用预定义变量的Makefile
Sources = main.c test.c
Objects = $(Sources:.c=.o)
EXE = main
CFLAGS := -Wall -O2 -fpic
$(EXE):$(Objects)
$(CC) $(CFLAGS) $^ -o $@
main.o:main.c
$(CC) $(CFLAGS) -c $^ -o $@
test.o:test.c
$(CC) $(CFLAGS) -c $^ -o $@
.PHONY:clean rebuild
clean:
$(RM) *.o