makefile如何编写?

什么是makefile?


        makefile文件中定义了一系列的规则来指定, 哪些文件需要先编译, 哪些文件需要后编译, 哪些文件需要重新编译, 甚至于进行更复杂的功能操作, 因为makefile就像一个Shell脚本一样, 其中也可以执行操作系统的命令.  makefile带来的好处就是——“自动化编译”, 一旦写好, 只需要一个make命令, 整个工程完全自动编译, 极大的提高了软件开发的效率.
        make是一个命令工具, 是一个解释makefile中指令的命令工具, 一般来说, 大多数的IDE都有这个命令, 比如:Visual C++的nmake, Linux下GNU的make. 可见, makefile都成为了一种在工程方面的编译方法.
        makefile文件中会使用gcc编译器对源代码进行编译, 最终生成可执行文件或者是库文件.

如何写makefile?

        写makefile要遵守他的规则,makefile由一组规则组成,规则如下:

目标: 依赖
(tab)命令

makefile基本规则三要素:

  • 目标: 要生成的目标文件
  • 依赖: 目标文件由哪些文件生成
  • 命令: 通过执行该命令由依赖文件生成目标

makefile中的变量

        在makefile中使用变量有点类似于C语言中的宏定义, 使用该变量相当于内容替换, 使用变量可以使makefile易于维护, 修改起来变得简单。

        makefile常见有两种类型的变量:普通变量、自带变量

普通变量:
变量定义直接用 =
使用变量值用 $(变量名)

//举例:变量的定义和使用
test= aaa			// 定义变量test并赋值为aaa
test1 = $(test)		// 使用变量, $(变量名)
//其中test1的值是test变量值的引用

除了使用用户自定义变量, makefile中也提供了一些变量(变量名大写)供用户直接使用, 我们可以直接对其进行赋值
CC = gcc     #arm-linux-gcc
CPPFLAGS : C预处理的选项 -I
CFLAGS :   C编译器的选项 -Wall -g -c
LDFLAGS :  链接器选项 -L  -l
自带变量:
$@: 表示规则中的目标
$<: 表示规则中的第一个条件
$^: 表示规则中的所有条件, 组成一个列表, 以空格隔开, 如果这个列表中有重复的项则消除重复项。
特别注意:自动变量只能在规则的命令中使用.

模式规则:至少在规则的目标定义中要包含’%’, ‘%’表示一个或多个, 在依赖条件中同样可以使用’%’, 依赖条件中的’%’的取值取决于其目标。(后边会举例子)

makefile函数

        makefile中的函数有很多, 在这里介绍两个最常用的:

1.	wildcard – 查找指定目录下的指定类型的文件
src=$(wildcard *.c)  //找到当前目录下所有后缀为.c的文件,赋值给src

2.	patsubst – 匹配替换
obj=$(patsubst %.c,%.o, $(src)) //把src变量里所有后缀为.c的文件替换成.o

makefile的清理操作

        用途: 清除编译生成的中间.o文件和最终目标文件

make clean 如果当前目录下有同名clean文件,则不执行clean对应的命令, 解决方案:
	伪目标声明: 
.PHONY:clean
	声明目标为伪目标之后, makefile将不会检查该目标是否存在或者该目标是否需要更新
	clean命令中的特殊符号:
	“-”此条命令出错,make也会继续执行后续的命令。如:“-rm main.o”
    rm -f: 强制执行, 比如若要删除的文件不存在使用-f不会报错
	“@”不显示命令本身, 只显示结果。如:“@echo clean done”
	其它
– make 默认执行第一个出现的目标, 可通过make dest指定要执行的目标
– make -f : -f执行一个makefile文件名称, 使用make执行指定的makefile: make -f mainmak

        举例:在linux下创建如下几个文件,并放到同一目录下,进行make和make clean操作。

//fun1.c代码如下:
#include <stdio.h>
void fun1()
{
    printf("this is fun1\n");	

}
//fun2.c代码如下:
#include <stdio.h>
void fun2()
{
    printf("this is fun2\n");	
}
//sum.c代码如下:
#include <stdio.h>

int sum(int len)
{
	int i = 0;
	int sum = 0;
	for(i=0; i<len; i++)
	{
		sum += i;
	}

	return sum;
}
//head.h
void fun1();
void fun2();
int sum(int len);
//main.c代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "head.h"

int main(int argc, char *argv[])
{
    printf("this is main!\n");
	int i = 0;
	for(i=0; i<argc; i++)
	{
		printf("[%d]:[%s]\n", i, argv[i]);
	}

    fun1();
    fun2();

	printf("sum(10)==[%d]\n", sum(10));

    return 0;
}

makefile里边的内容:

src=$(wildcard ./*.c)
object=$(patsubst %.c, %.o, $(src))
target=main
CC=gcc
CPPFLAGS=-I./

$(target):$(object)
	$(CC) -o $@ $^

%.o:%.c
	$(CC) -o $@ -c $< $(CPPFLAGS) 

.PHONY:clean
clean:
	-rm -f $(target) $(object)

结果如下:

编写makefile要掌握其套路,常用的方法和操作在上边已有呈现,下边是本次makefile文件编写的注释,帮助我们理解。
 

# 查找当前目录下所有的 .c 源文件
src=$(wildcard ./*.c)

# 将 src 变量中所有后缀为 .c 的文件替换为对应的 .o 文件
object=$(patsubst %.c, %.o, $(src))

# 定义目标文件名为 main,target 为普通变量
target=main

# 指定编译器为 gcc
CC=gcc

# 编译时使用的预处理器选项,包含当前目录
CPPFLAGS=-I./

# 定义 main 目标及其依赖对象
$(target): $(object)
		$(CC) -o $@ $^  # 使用 gcc 链接生成最终可执行文件

# 定义规则,将 .c 文件编译成 .o 文件
%.o: %.c
		$(CC) -o $@ -c $< $(CPPFLAGS)  # 编译源文件,生成目标文件

# 声明 clean 为伪目标,以便不受文件名影响而被执行
.PHONY: clean

# 定义清理操作,删除生成的目标和对象文件
clean:
		-rm -f $(target) $(object)  # 移除生成的可执行文件和对象文件,-f 表示强制删除,不提示错误信息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值