makefile写法

本文深入解析Makefile的两种基础写法,包括其如何简化编译过程和自动化管理源代码。通过实例演示,展示了如何利用Makefile进行高效编译,特别针对大型工程的编译优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在例子中说明makefile写法

直接举例说明。有如下源程序。

 

/* main.c */
#include "mytool1.h"
#include "mytool2.h"
int main(int argc,char **argv)
{
mytool1_print("hello");
mytool2_print("hello");
}

 

/* mytool1.h */
#ifndef _MYTOOL_1_H
#define _MYTOOL_1_H
	void mytool1_print(char *print_str);
#endif

 

/* mytool1.c */
#include "mytool1.h"
void mytool1_print(char *print_str)
{
	printf("This is mytool1 print %s ",print_str);
}

 


/* mytool2.h */
#ifndef _MYTOOL_2_H
#define _MYTOOL_2_H
	void mytool2_print(char *print_str);
#endif

 

/* mytool2.c */
#include "mytool2.h"
void mytool2_print(char *print_str)
{
	printf("This is mytool2 print %s ",print_str);
}

一般的编译步骤:

 

gcc -c main.c
gcc -c mytool1.c
gcc -c mytool2.c
gcc -o main main.o mytool1.o mytool2.o

这样我们就生成了我们需要的可运行的main文件。

但是当我们的工程很大的时候,有时候修改了几个源文件,我们得按照上面的一般编译步骤重新敲命令就很麻烦了,所以需要利用makefile来维护。

 

makefile有两种标准写法。

makefile基础认识

先有个感性的认识。

第一种形如:

 

main:main.o mytool1.o mytool2.o
	gcc -o main main.o mytool1.o mytool2.o
main.o:main.c mytool1.h mytool2.h
	gcc -c main.c
mytool1.o:mytool1.c mytool1.h
	gcc -c mytool1.c
mytool2.o:mytool2.c mytool2.h
	gcc -c mytool2.c

备注一下:

其实上面的依赖关系中,*.h文件都可以去掉。因为规则中并无*.h文件。举例说明如下:

mytool1.c文件中#include "mytool1.h"文件,即便makefile中mytool1.o不写上依赖mytool1.h,当mytool1.h文件内容改变时候,由于mytool1.c文件包含了mytool1.h文件,所以mytool1.c文件内容实际也是改变了的,所以依然会执行生成mytool1.o文件的规则。

第二种形如:

 

 

OBJS = main.o mytool1.o mytool2.o
CC = gcc
CFLAGS = -Wall -O -g
main:$(OBJS)
        $(CC) $(OBJS) -o main
main.o:main.c mytool1.h mytool2.h
        $(CC) $(CFLAGS) -c $< -o main.o
mytool1.o:mytool1.c mytool1.h
        $(CC) $(CFLAGS) -c $< -o $@
mytool2.o:mytool2.c mytool2.h
        $(CC) $(CFLAGS) -c $< -o $@

.PHONY: clean
clean:
        rm *.o main

 

makefile写法

一般的格式是:
目标文件 : 依赖文件
tab键缩进 编译规则
当倚赖的对象在目标修改后修改的话,就要去执行规则一行所指定的命令。
(注意一定要是tab键缩进,否则会报错如下)
Makefile有三个非常有用的变量。分别是$@,$^,$<代表的意义分别是:
$@ -- 目标文件
$^ -- 所有的依赖文件
$< -- 第一个依赖文件
$+ -- $+和$^类似,也是所有的依赖文件,只是它不取出重复的依赖目标
如果我们使用上面三个变量,那么我们可以简化我们的Makefile文件为:
# 这是简化后的Makefile
main:main.o mytool1.o mytool2.o
gcc -o $@ $^
main.o:main.c mytool1.h mytool2.h
gcc -c $<
mytool1.o:mytool1.c mytool1.h
gcc -c $<
mytool2.o:mytool2.c mytool2.h
gcc -c $<
经过简化后,我们的Makefile是简单了一点,不过人们有时候还想简单一点。这里我们学习一个Makefile的缺省规则。
.c.o:
gcc -c $<
这个规则表示所有的 .o文件都是依赖与相应的.c文件的。
例如mytool.o依赖于mytool.c这样Makefile还可以变为:
# 这是再一次简化后的Makefile
main:main.o mytool1.o mytool2.o
gcc -o $@ $^
.c.o:
gcc -c $<

makefile一些函数

addprefix 加前缀函数

patsubst 替换通配符

notdir 去除路径

wildcard 扩展通配符

函数wildcard得到指定目录下所有的C语言源程序文件名的方法,这下好了,不用手工一个一个指定需要编译的.c文件了,方法如下:
SRC = $(wildcard *.c)
等于指定编译当前目录下所有.c文件,如果还有子目录,比如子目录为inc,则再增加一个wildcard函数,象这样:
SRC = $(wildcard *.c) $(wildcard inc/*.c)
 
 
例子:
建立一个测试目录,在测试目录下建立一个名为sub的子目录
$ mkdir test
$ cd test
$ mkdir sub

在test下,建立a.c和b.c 两个文件,在sub目录下,建立sa.c和sb.c 两个文件

建立一个简单的Makefile
src=$(wildcard *.c ./sub/*.c)
dir=$(notdir $(src))
obj=$(patsubst %.c,%.o,$(dir) )

all:
@echo $(src)
@echo $(dir)
@echo $(obj)
@echo "end"

执行结果分析:
第一行输出:
a.c b.c ./sub/sa.c ./sub/sb.c
wildcard把 指定目录 ./ 和 ./sub/ 下的所有后缀是c的文件全部展开。

第二行输出:
a.c b.c sa.c sb.c
notdir把展开的文件去除掉路径信息

第三行输出:
a.o b.o sa.o sb.o

在$(patsubst %.c,%.o,$(dir) )中,patsubst把$(dir)中的变量符合后缀是.c的全部替换成.o,
任何输出。
或者可以使用
obj=$(dir:%.c=%.o)
效果也是一样的。

这里用到makefile里的替换引用规则,即用您指定的变量替换另一个变量。
它的标准格式是
$(var:a=b) 或 ${var:a=b}
它的含义是把变量var中的每一个值结尾用b替换掉a。

makefile一些细节问题

符号“=”、“:=”、“?=”、“+=”的区别

= 是最基本的赋值
:= 是覆盖之前的值
?= 是如果没有被赋值过就赋予等号后面的值
+= 是添加等号后面的值
 
举个例子说明:
1、“=”
make会将整个makefile展开后,再决定变量的值。也就是说,变量的值将会是整个makefile中最后被指定的值。看例子:
x = foo
y = $(x) bar
x = xyz

在上例中,y的值将会是 xyz bar ,而不是 foo bar 。


2、“:=”
“:=”表示变量的值决定于它在makefile中的位置,而不是整个makefile展开后的最终值。
x := foo
y := $(x) bar
x := xyz

在上例中,y的值将会是 foo bar ,而不是 xyz bar 了。
 
 
 
如此,makefile基础功能应该也都会使用了。要了解更细致的makefile规则,请查看makefile官方文档。
 
 
 
 
 
 
 
 
 
 
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值