一、make工具和Makefile文件的引入
当源码文件比较多的时候就不适合通过直接输入gcc命令来编译,这时候就需要一个自动化的编译工具.
make:一般说GNU Make,是一个软件,用于将源代码文件编译为可执行的二进制文件,make工具主要用于完成自动化编译。make工具编译的时候需要Makefile文件提供编译文件。
Makefile:make工具所使用的文件,Makefile指明了编译规则。
在编程过程中,我们经常会使用make工具来自动化编译和构建项目。make工具可以根据Makefile文件中的规则来判断源代码的依赖关系,并且自动编译和构建项目。
首先,我们需要安装make工具。在Linux系统下,可以使用以下命令进行安装:
sudo apt-get install build-essential
在Windows系统中,可以下载并安装GNU Make工具。
接下来,我们需要创建一个Makefile文件。Makefile文件包含了项目的编译和构建规则。
一个简单的Makefile示例:
# 定义变量
CC = gcc
CFLAGS = -Wall
# 定义规则
all: myprogram
myprogram: main.o foo.o bar.o
$(CC) $(CFLAGS) -o myprogram main.o foo.o bar.o
main.o: main.c
$(CC) $(CFLAGS) -c main.c
foo.o: foo.c
$(CC) $(CFLAGS) -c foo.c
bar.o: bar.c
$(CC) $(CFLAGS) -c bar.c
clean:
rm -f *.o myprogram
在这个示例中,我们定义了一些变量,比如编译器的路径和编译选项。然后,我们定义了一个规则all
,依赖于myprogram
目标。myprogram
目标依赖于main.o
、foo.o
和bar.o
,分别编译了这些源文件并链接成可执行文件myprogram
。我们还定义了一个clean
规则,用来清理生成的目标文件和可执行文件。
要使用make工具来编译和构建项目,只需要在命令行中进入项目目录,并运行make
命令即可:
make
make工具会自动读取Makefile文件,并根据规则来编译和构建项目。
要使用make工具来清理生成的目标文件和可执行文件,只需要在命令行中进入项目目录,并运行make clean
命令即可
make clean
二、编写C程序
编写一个小型的含有多个.c文件的C程序。
在项目的源代码文件中,我们可以使用#include指令来引入需要的头文件,例如:
main.c文件:
#include "foo.h"
#include "bar.h"
int main() {
// Do something
return 0;
}
foo.c文件:
#include "foo.h"
void foo() {
// Do something
}
bar.c文件:
#include "bar.h"
void bar() {
// Do something
}
在上述文件中,我们在main.c、foo.c和bar.c中分别引入了需要使用的头文件foo.h和bar.h。
三、使用make工具和Makefile文件编译
首先,创建一个名为Makefile的文件,内容如下:
CC = gcc
CFLAGS = -Wall -g
SRC = main.c foo.c bar.c
OBJ = $(SRC:.c=.o)
TARGET = myprogram
all: $(TARGET)
$(TARGET): $(OBJ)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJ)
clean:
rm -f $(OBJ) $(TARGET)
在上述Makefile中,我们定义了编译器CC,编译选项CFLAGS,源代码文件SRC,目标文件OBJ和目标程序名称TARGET。
最后,使用命令make来执行Makefile文件中定义的编译规则,即可自动进行源代码的编译和链接,生成目标程序。
$ make
执行以上命令后,Make工具会根据Makefile文件中的定义进行编译,生成名为myprogram的目标程序。
如果需要清理编译生成的文件,可以使用命令make clean:
$ make clean
这样就可以删除编译生成的目标文件和目标程序。
四、Makefile规则
4.1关于Makefile 自动化变量
4.2伪目标
Makefile 有一种特殊的目标——伪目标,一般的目标名都是要生成的文件,而伪目标不代表真正的目标名,在执行 make 命令的时候通过指定这个伪目标来执行其所在规则的定义的命令。 使用伪目标主要是为了避免 Makefile 中定义的执行命令的目标和工作目录下的实际文件出现名字冲突,有时候我们需要编写一个规则用来执行一些命令,但是这个规则不是用来创建文件的
.PHONY : clean
clean:
rm -f $(OBJ) $(TARGET)
.PHONY : clean 声明 clean 为伪目标,声明 clean 为伪目标以后不管当前目录下是否存在名为“clean”的文件,输入“make clean”的话规则后面的 rm 命令都会执行。
4.3条件判断
语法有两种如下:
<条件关键字>
<条件为真时执行的语句>
endif
以及:
<条件关键字>
<条件为真时执行的语句>
else
<条件为假时执行的语句>
endif
其中条件关键字有 4 个:ifeq、ifneq、ifdef 和 ifndef,这四个关键字其实分为两对、ifeq 与 ifneq、ifdef 与 ifndef,先来看一下 ifeq 和 ifneq,ifeq 用来判断是否相等,ifneq 就是判断是否不 相等,ifeq 用法如下:
ifeq (参数 1>, 参数 2>)
ifeq ‘参数 1 >’,‘ 参数 2>’
ifeq “参数 1>”, “参数 2>”
ifeq “参数 1>”, ‘参数 2>’
ifeq ‘参数 1>’, “参数 2>”
上述用法中都是用来比较“参数 1”和“参数 2”是否相同,如果相同则为真,“参数 1”和 “参数 2”可以为函数返回值。ifneq 的用法类似,只不过 ifneq 是用来了比较“参数 1”和“参 数 2”是否不相等,如果不相等的话就为真。 ifdef 和 ifndef 的用法如下:
ifdef 变量名>
如果“变量名”的值非空,那么表示表达式为真,否则表达式为假。“变量名”同样可以是 一个函数的返回值。ifndef 用法类似,但是含义用户 ifdef 相反。
4.4 Makefile 支持函数
Makefile 支持函数,类似 C 语言一样,Makefile 中的函数是已经定义好的,我们直接使用, 不支持我们自定义函数。make 所支持的函数不多,但是绝对够我们使用了,函数的用法如下: $(函数名 参数集合) 或者: ${函数名 参数集合} 可以看出,调用函数和调用普通变量一样,使用符号“$”来标识。参数集合是函数的多个 参数,参数之间以逗号“,”隔开,函数名和参数之间以“空格”分隔开,函数的调用以“$”开 头。
函数 subst 函数 subst 用来完成字符串替换,调用形式如下:
$(subst<from> ,<to>,<text>) 此函数的功能是将字符串中的内容替换为,函数返回被替换以后的字符串,比如如下示例:
$(subst aab,AAB,my name is aab)
把字符串“my name is aab”中的“aab”替换为“AAB”,替换完成以后的字符串为“my name is AAB”。
函数 patsubst 用来完成模式字符串替换,使用方法如下: $(patsubst<pattern> ,<replacement>,<text>)
函数 dir 用来获取目录,使用方法如下: $(dir <name…>)
函数 notdir 去除文件中的目录部分,也就是提取文件名,用法如下: $(notdir <name…>)
foreach 函数用来完成循环,用法如下: $(foreach <var>,<list> ,<text>)
通配符“%”只能用在规则中,只有在规则中它才会展开,如果在变量定义和函数使用时, 通配符不会自动展开,这个时候就要用到函数 wildcard,使用方法如下:
$(wildcard PATTERN…)
比如: $(wildcard *.c)
上面的代码是用来获取当前目录下所有的.c 文件,类似“%”