Linux下C语言的makefile

本文详细介绍了Linux环境下C语言的Makefile,包括其作用、工作原理、实例解析、参数使用以及宏定义。通过Makefile,可以自动化管理编译过程,提高效率。文中给出了两个实例,演示了如何编写和使用Makefile,以及如何处理多依赖文件的场景。此外,还提到了make命令的常用参数,如-k和-n,以及宏定义中的特殊符号。通过对Makefile的学习和使用,开发者可以更有效地管理C语言项目。
摘要由CSDN通过智能技术生成

Linux下C语言的makefile

0.定义

工程管理器,顾名思义,是指管理较多的文件,Make工程管理器也就是个“自动编译管理器”,这里的“自动”是指它能够根据文件时间戳自动发现更新过的文件而减少编译的工作量,同时,它通过读入Makefile文件文件的内容来执行大量的编译工作,Make将只编译改动的代码文件,而不用完全编译。

Makefile文件一般和项目的其他源文件放在同一个目录下。在机器上可以同时存在许多不同的makefile文件,如果一个大项目,可以用多个不同的makefile文件来分别管理项目的不同部分。

Make命令和makefile文件的结合提供了有一个在项目管理领域十分强大的工具,不仅可以用于控制源代码的编译,而且还可以用于手册也的编写以及将应用程序安装到目标目录。

1)如果这个工程没有编译过,那么我们的所有C文件都要编译并被链接。
2)如果这个工程的某几个C文件被修改,那么我们只编译被修改的C文件,并链接目标程序。
3)如果这个工程的头文件被改变了,那么我们需要编译引用了这几个头文件的C文件,并链接目标程序。
只要我们的Makefile写得够好,所有的这一切,我们只用一个make命令就可以完成,make命令会自动智能地根据当前的文件修改的情况来确定哪些文件需要重编译,从而自己编译所需要的文件和链接目标程序。

1.实例

a.实例1

main:main.o
	gcc main.o -o main
main.o:main.c
	gcc -c main.c 
clean:
	rm -rf main.o main

img

会经过编译(-c) 和 生成(-o)out文件(默认生成a.out)

b.实例2

all:ser
ser:ser.o thread.o
	gcc -o ser ser.o thread.o -lpthread
ser.o:ser.c
	gcc -c ser.c
thread.o:thread.c
	gcc -c thread.c -g
clean:
	rm -rf *.o ser

说明:

语句含义
all:ser表示最终生成的文件是ser
ser:ser.o thread.oser的依赖文件是ser.o和thread.o
gcc -o ser ser.o thread.o -lpthread接的过程(thread.o是一个多线程文件所以加上了-lpthread)
ser.o:ser.cser.o的依赖文件是ser.c
gcc -c ser.c编译ser.c 为 ser.o
thread.o:thread.cthread.o的依赖文件是thread.c
gcc -c thread.c -g编译thread.c 为 thread.o
clean: rm -rf *.o ser执行clean命令后删除所有的.o文件和ser目标文件

2.make的参数

  • -k:作用是在让make命令在发现错误时仍然就执行,而不是在检测到第一个错误时就停止,所以可是使用这个选项在一次操作中发下所有未编译成功的源文件

  • n:作用是让make命令输出将要执行的操作步骤,而不是真正执行这些操作

  • -f <filename>:作用是告诉make将文件名为filename的我文件作为makefile文件。如果未使用这个选项,标准版的make命令将优先在当前命令下查找名称为makefile的文件,如果不存在名称makefile的文件,则开始查找名为Makefile的文件。

比如新建文件makefile

all:
   @echo ""
   @echo "This is a makefile test "
   @echo "End test"
   @echo ""

然后在终端运行:

img

然后再新建Makefile(注意这里是大写)

all:
   @echo ""
   @echo "This is a Makefile test "
   @echo "End test"
   @echo ""

运行后

img

然后使用**-f**选项,

all:
    @echo ""
    @echo "This is a make command test"
    @echo "End test"
    @echo ""

可以看出已经不识别makefile的语法高亮,那使用**-f选项指定运行maketest**文件,效果如下。img

因此默认会生成makefile 若找不到则会找Makefile ,若要在多个makefile指定一个,则可使用-f 唯一指定filename。

3.make的工作原则

make会一层一层的找文件的依赖关系,直到最终编译出第一个目标文件。在过程中如果出现错误则直接退出,并报错。

4.makefile 的宏定义

a.预定义变量

CC:C编译器的名称,默认cc;
CFLAGS :C编译器的选项,无默认值;
CXXFLAGS:C++编译器的选项,无默认值;

OBJS=talent.o hardwork.o
CC=gcc
CFLAGS=-Wall -O -g
success:$(OBJS)
        $(CC) $(CFLAGS) $^ -o success
talent.o:talent.c talent.h
        $(CC) $(CFLAGS) $^ -o talent.o
hardwork.o:hardwork.c hardwork.h
        $(CC) $(CFLAGS) $^ -o hardwork.o

Makefile中的特殊宏定义:

可以通过KEY=value在makefile中定义宏。可以使用** ( K E Y ) 或 者 (KEY)或者 (KEY){KEY}引用宏**

makefile1:

main:main.o
	gcc main.o -o main
main.o:main.c
	gcc -c main.c 
clean:
	rm -rf main.o main

可以将上述的文件makefile1修改成makefile2:

-Wall :表示允许发出gcc所有有用的报警信息。

-g 只是编译器,在编译的时候,产生调试信息。

makefile2:

CC = gcc
CFLAGS = -g -Wall -O 
 
main:main.o
	$(CC) main.o -o main
main.o:main.c
	$(CC) $(CFLAGS) -c main.c 
clean:
	rm -rf main.o main

终端执行命令make -f makefile2,可以看到:

img

b.宏定义符号

宏定义符号含义
$*不包括后缀名的当前依赖文件的名称
$+所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件
$<第一个依赖文件的名称
$?所有时间戳比目标文件晚的依赖文件,并以空格分开
$@目标文件的完整名称
$^所有不重复的目标依赖文件,以空格分开
-:告诉make命令忽略所有的错误
@:告诉make在执行命令前不要该改命令显示在标准输出上

那么,上面的makefile2可以修改为:

CC = gcc
CFLAGS = -g -Wall -O 
main:main.o
	$(CC) $^ -o $@
%.o:%.c
	$(CC) $(CFLAGS) -c $^
clean:
	rm -rf main.o main

5.多个依赖文件的编写

main.c,add.c,add.h,sub.c,aub.h

main.c的内容为:

#include <stdio.h>
#include "add.h"
#include "sub.h"
 
int main()
{
    int a = 10, b = 5;
    printf("a + b = %d\r\n", add(a, b));
    printf("a - b = %d\r\n", sub(a, b));
    return 0;
}

那么makefile可以这样写:

CC = gcc
CFLAGS = -g -O  -Wall
 
main:add.o sub.o main.o 
	$(CC) $^ -o $@
%.o:%.c
	$(CC) $(CFLAGS) -c $^
clean:
	rm -rf main main.o add.o sub.o

在终端运行make命令后:

img


当依赖目标新于目标时,也就是当规则的目标需要被更新时,make 会一条一条的执行其后的命令。需要注意的是,如果你要让上一条命令的结果应用在下一条命令时,你应该使用分号分隔这两条命令。比如你的第一条命令是 cd 命令,你希望第二条命令得在 cd 之后的基础上运行,那么你就不能把这两条命令写在两行上,而应该把这两条命令写在一行上,用分号分隔。如:

示例一:

exec:
	cd /home/hchen
	pwd

示例二:

exec:
	cd /home/hchen; pwd

当我们执行“make exec”时,第一个例子中的 cd 没有作用,pwd 会打印出当前的Makefile 目录,而第二个例子中,cd 就起作用了,pwd 会打印出“/home/hchen”。

6.参考文章

传送门1

传送门2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

酷酷的Herio

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值